A Simple Class Program Example
This example will show you how to:
1. Start Microsoft Visual C++/Studio .NET. 2. From the File menu, select New and then select Project. The New Project dialog box appears.
|
3. Set the Project Type to CLR Projects.
4. Set the Templates to CLR Console Application.
5. Type Animals in the Name text box.
6. Choose appropriate location for the new project. Click OK.
7. In Solution Explorer, double-click the Animals.cpp file in the Source Files folder.
8. Immediately under the using namespace System; line, add the following class definition:
ref class Animal
{
int legs;
String^ strName;
};
To declare a class in C++, you use the keyword class followed by a name for the class, such as Animal in this example, and then you list all the class’s member variables, functions, and methods between an opening brace ({) and a closing brace (}). So far, you have created an Animal class with an int variable for the number of its legs and a String variable for its name. As it stands, no other program or class will be able to access these variables. The members of a class, data and methods, are private by default and can only be accessed by methods of the class itself. C++ provides three access modifiers: public, private, and protected, to specify the visibility of the various members of the class.
9. Add the keyword public followed by a colon (:) on a new line between the opening brace and the first variable declaration, as shown here:
ref class Animal
{
public:
int legs;
String^ strName;
};
Declaring the variables after the keyword public makes both of them accessible. However, it is not usually a good idea to allow other classes and parts of your program access to the variables of a class. As discussed earlier in the section on encapsulation, it’s better to keep the implementation details of a class hidden from users of that class and to control the access to the class’s data through functions. In this example, the keyword private will be used to prevent direct access to the String variable of the class. The int variable legs will be left with public access, simply to show how it can then be directly accessed by the main program.
10. Add the keyword private followed by a colon (:) between the first int variable and the second String variable, as shown here:
ref class Animal
{
public:
int legs;
private:
String^ strName;
};
To provide access to the private String variable, public accessor functions and methods need to be added to the class to allow other functions to manipulate its value.
11. After the declaration of the int variable and before the private access modifier, add the following method declarations or implementation lines:
void SetName(String^ name) { strName = strName->Copy(name); }
String^ GetName() { return strName; }
Because these methods are small functions, it’s easiest to declare and implement them as in-line functions. The Animal class is now complete. The syntax of the declaration is:
ref class classname
{
Access control keywords (public, private or protected)
The declaration of class variables and methods
}
More complete syntax is given below.
class_access ref class name modifier : inherit_access base_type { };
Example:
ref class MyClass2 {
public:
int i;
};
ref class MyClass2 : public MyClass::MyInterface {
public:
virtual void f() { System::Console::WriteLine("testing 1..2..3"); }
You have probably noticed the ref keyword. This keyword is one of the new C++ keyword (Managed Extensions for C++ uses __gc) that simplifies the interaction with .NET Framework components. By placing ref in front of the class keyword, the class becomes a managed class. When the object is instantiated, it will be created on the common language runtime (CLR) heap and the gcnew (instead of new) operator will return the memory address of this object. The lifetime of an object instantiated from the class will be managed by the .NET Framework’s garbage collector. When the object falls out of scope, the memory used by the object will be garbage-collected and no explicit calls to delete (such as delete keyword) will have to be made. ref classes are known as reference types because the variable does not actually contain the object but a pointer to the memory where the object is. However, there are performance issues to consider when using reference types. The memory has to be allocated from the managed heap, which could force a garbage collection to occur. In addition, reference types have to be accessed via their pointers, affecting both the size and speed of the compiled application. Because of these performance issues, the .NET Framework also supports value types. Value types are objects created on the stack. The variable contains the object itself rather than a pointer to the object. Hence, the variable doesn’t have to be dereferenced to manipulate the object, which of course improves performance. To declare a value type class, the value keyword should be used instead of the ref keyword. In this case, the variables would have been created on the stack. Instead of declaring pointers for this class and then creating the objects on the CLR heap by using the new operator, the objects would have been declared in the same way as the built-in C++ types and the member variables accessed by the dot operator (.) rather than via the dereferencing operator (->). Now that the Animal class has been constructed, it can be used by the program just as the program would use a built-in type.
12. In the main() function, delete the following line:
Console::WriteLine(L"Hello World");
13. Declare and create two Animal objects in your main() function, as shown here:
Animal ^ lizard = gcnew Animal;
Animal ^ bird = gcnew Animal;
The keyword gcnew followed by the class of the object being created creates the object on the CLR heap rather than on the stack. The memory address of the created object is returned and stored in the pointer.
14. Use the member function SetName to assign the names Lizard and Bird to the respective lizard and bird objects, and set the legs variable for both objects as shown below.
lizard->SetName("Lizard");
lizard->legs = 4;
bird->SetName("Bird");
bird->legs = 2;
To access the member variables and functions, you have to dereference the pointer in one of two ways. You can use:
The dereferencing operator, an asterisk (*) followed by the dot notation, for example, (*lizard).legs.
You can also use the shorthand operator for indirect access, which is a minus sign and right angle bracket (->).
15. Having created a couple of Animal objects and assigned data to them, you are now going to display that data on the screen. Add the following lines:
Console::WriteLine("Animal object #1");
Console::Write("Name: ");
Console::WriteLine(lizard->GetName());
Console::Write("Legs: ");
Console::WriteLine(lizard->legs);
Console::WriteLine();
Console::WriteLine("Animal object #2");
Console::Write("Name: ");
Console::WriteLine(bird->GetName());
Console::Write("Legs: ");
Console::WriteLine(bird->legs);
Console::WriteLine();
16. Build the application. Select Build Solution from the Build menu bar, or use the keyboard shortcut Ctrl+Shift+B.
In case you’ve had any problems putting the program together from the fragments in the preceding steps, the entire program is listed here:
// Animal.cpp : main project file.
#include "stdafx.h"
using namespace System;
ref class Animal
{
public:
int legs;
void SetName(String^ name) { strName = strName->Copy(name); }
String^ GetName() { return strName; }
private:
String^ strName;
};
int main(array<System::String ^> ^args)
{
Animal ^ lizard = gcnew Animal;
Animal ^ bird = gcnew Animal;
lizard->SetName("Lizard");
lizard->legs = 4;
bird->SetName("Bird");
bird->legs = 2;
Console::WriteLine("Animal object #1");
Console::Write("Name: ");
Console::WriteLine(lizard->GetName());
Console::Write("Legs: ");
Console::WriteLine(lizard->legs);
Console::WriteLine();
Console::WriteLine("Animal object #2");
Console::Write("Name: ");
Console::WriteLine(bird->GetName());
Console::Write("Legs: ");
Console::WriteLine(bird->legs);
Console::WriteLine();
return 0;
}
17. If the build was successful, run the application by selecting Start Without Debugging from the Debug menu, or use the keyboard shortcut Ctrl+F5.
The output is shown below.