Home

Classes and their Methods

 

Methods and Parameters 

 

Methods Arguments

Like regular functions, the methods of a class can use some arguments to carry their assignments. To pass an argument to a method, simply type it in the parentheses. By design, the member variables of an object are accessible to the methods of the same object. This means that you do not have to pass their equivalents to your methods.

Practical LearningPractical Learning: Introducing Data Reading

  1. Start Microsoft Visual C++ 2005
  2. On the main menu, click File -> New -> Project...
  3. On the left side, make sure that Visual C++ is selected. In the Templates list, click CLR Empty Project
  4. In the Name box, replace the string with ElectroStore2 and click OK
  5. On the main menu, click Project -> Add New Item...
  6. To create a header file, in the Templates list, click Header File (.h)
  7. Set the Name to StoreItem and click Add
  8. Complete the file as follows:
     
    #pragma once
    using namespace System;
    
    namespace ElectronicsStore
    {
        public ref class CStoreItem
        {
        private:
            long        nbr;
            __wchar_t ^ cat;
            String    ^ mk;
            String    ^ mdl;
            double      discount;
            double      price;
    
        public:
            inline long        GetItemNumber();
            inline __wchar_t ^ GetCategory();
            inline String    ^ GetMake();
            inline String    ^ GetModel();
            inline double      GetDiscountRate();
            inline double      GetUnitPrice();
        };
    }
  9. To create a source file, on the main menu, click Project -> Add New Item...
  10. In the Templates list, click C++ File (.cpp)
  11. Set the Name to StoreItem and press Enter
  12. Complete the file as follows:
     
    #include "StoreItem.h"
    using namespace System;
    
    namespace ElectronicsStore
    {
        inline long CStoreItem::GetItemNumber()
        {
    	return nbr;
        }
    
        inline __wchar_t ^ CStoreItem::GetCategory()
        {
    	return cat;
        }
    
        inline String ^ CStoreItem::GetMake()
        {
    	return mk;
        }
    
        inline String ^ CStoreItem::GetModel()
        {
    	return mdl;
        }
    
        inline double CStoreItem::GetDiscountRate()
        {
    	return discount / 100;
        }
    
        inline double CStoreItem::GetUnitPrice()
        {
    	return price;
        }
    }
  13. To create one more source file, on the main menu, click Project -> Add New Item...
  14. In the Templates list, make sure C++ File (.cpp) is selected.
    Set the Name to Exercise and click Add
  15. Complete the file as follows:
     
    #include "StoreItem.h"
    
    using namespace System;
    using namespace ElectronicsStore;
    
    int main()
    {
        String ^ strTitle = L"=-= Nearson Electonics =-=\n"
    		        L"******* Store Items ******";
        CStoreItem ^ sItem = gcnew CStoreItem;    
    
        Console::WriteLine();
        return 0;
    }
  16. Save all

Constant Arguments

In previous lessons, we learned that when a function received an argument that it didn't modify, the argument should be declared as constant. This allows the compiler to make sure that the argument would not be modified. The same technique applies to an argument used by a method of a class.

To declare an argument of an object’s method as constant, type the const keyword on the left of the argument’s data type. Consider a box object as follows:

Box

We would like to know the area of each side because different things will be displayed on each side and we need to know how much space is available. If we were dealing with a rectangle, we would just declare an area method as follows:

double FaceArea();

On a box (rectangular parallelepiped), we have three rectangle types that represent the six faces. We can declare one method that takes any two sides and calculates their area. Such a method would be declared as follows:

double FaceArea(double side1, double side2);

We can define it as follows:

public value struct CBox
{
    double FaceArea(double length, double height)
    {
        double area = length * height;
        return area;
    }
};

Notice that the method doesn't modify the values of the arguments it uses. Therefore, they should be declared as constants. To declare each as constant, you would change the declaration of the method as follows:

double Area(const double side1, const double side2);

Here is an example of a class with methods that take constant arguments:

using namespace System;

public value class CBox
{
public:
    double FaceArea(const double length, const double height)
    {
        double area = length * height;
        return area;
    }
    double TopArea(const double length, const double width)
    {
        return length * width;
    }

    double RightArea(const double height, const double width)
    {
        return height * width;
    }
};

int main()
{
    CBox ^ box = gcnew CBox;

    const double L = 35.85;
    const double H = 28.46;
    const double W = 22.08;

    Console::WriteLine(" -=- Box Areas -=-");
    Console::WriteLine("Top:   {0}", box->TopArea(L, W));
    Console::WriteLine("Face:  {0}", box->FaceArea(L, H));
    Console::WriteLine("Right: {0}", box->RightArea(H, W));
    
    return 0;
}

This would produce:

-=- Box Areas -=-
Top:   791.568
Face:  1020.29
Right: 628.397
Press any key to continue...
 

Practical LearningPractical Learning: Passing Constant Arguments

  1. Access the StoreItem.h header file
  2. To create methods with constant arguments, change the file as follows:
     
    #pragma once
    using namespace System;
    
    namespace ElectronicsStore
    {
        public ref class CStoreItem
        {
        private:
            long        nbr;
            __wchar_t ^ cat;
            String    ^ mk;
            String    ^ mdl;
            double      discount;
            double      price;
    
    	public:
            inline long        GetItemNumber();
            inline void        SetItemNumber(const long number);
            inline __wchar_t ^ GetCategory();
            inline void        SetCategory(__wchar_t ^ category);
            inline String    ^ GetMake();
            inline void        SetMake(String ^ make);
            inline String    ^ GetModel();
            inline void        SetModel(String ^ model);
            inline double      GetDiscountRate();
            inline void        SetDiscountRate(const double discountRate);
            inline double      GetUnitPrice();
            inline void        SetUnitPrice(const double unitPrice);
        };
    }
  3. Access the StoreItem.cpp source file
  4. To define methods that take constant arguments, implement the new methods as follows:
     
    #include "StoreItem.h"
    using namespace System;
    
    namespace ElectronicsStore
    {
        inline long CStoreItem::GetItemNumber()
        {
            return nbr;
        }
    
        inline void CStoreItem::SetItemNumber(const long number)
        {
    	this->nbr = number;
        }
    
        inline __wchar_t ^ CStoreItem::GetCategory()
        {
    	return cat;
        }
    
        inline void CStoreItem::SetCategory(__wchar_t ^ category)
        {
    	this->cat = category;
        }
    
        inline String ^ CStoreItem::GetMake()
        {
    	return mk;
        }
    
        inline void CStoreItem::SetMake(String ^ make)
        {
    	this->mk = make;
        }
    
        inline String ^ CStoreItem::GetModel()
        {
    	return mdl;
        }
    
        inline void CStoreItem::SetModel(String ^ model)
        {
    	this->mdl = model;
        }
    
        inline double CStoreItem::GetDiscountRate()
        {
    	return discount / 100;
        }
    
        inline void CStoreItem::SetDiscountRate(const double discountRate)
        {
    	this->discount = discountRate;
        }
    
        inline double CStoreItem::GetUnitPrice()
        {
    	return price;
        }
    
        inline void CStoreItem::SetUnitPrice(const double unitPrice)
        {
            this->price = unitPrice;
        }
    }
  5. Access the Exercise.cpp source file
  6. To use the new methods, change the file as follows:
     
    #include "StoreItem.h"
    
    using namespace System;
    using namespace ElectronicsStore;
    
    CStoreItem ^ CreateStoreItem();
    void DescribeStoreItem(CStoreItem ^ %);
    
    int main()
    {
        String ^ strTitle = L"=-= Nearson Electonics =-=\n"
    		                L"******* Store Items ******";
        CStoreItem ^ storeItem = CreateStoreItem();       
    
        Console::WriteLine();
        Console::WriteLine(strTitle);
        DescribeStoreItem(storeItem);
    
        Console::WriteLine();
        return 0;
    }
    
    CStoreItem ^ CreateStoreItem()
    {
        long        number;
        __wchar_t ^ category;
        String    ^ make;
        String    ^ model;
        double      discount;
        double      price;
    
        Console::WriteLine(L"To create a store item, enter its information");
        Console::Write(L"Item Number: ");
        number = long::Parse(Console::ReadLine());
        Console::WriteLine(L"Category");
        Console::WriteLine(L"A - Audio Cables");
        Console::WriteLine(L"B - Batteries");
        Console::WriteLine(L"C - Cell Phones and Accessories");
        Console::WriteLine(L"D - Bags and Cases");
        Console::WriteLine(L"H - Headphones");
        Console::WriteLine(L"M - Digital Cameras");
        Console::WriteLine(L"O - Cables and Connectors");
        Console::WriteLine(L"P - PDAs and Accessories");
        Console::WriteLine(L"T - Telephones and Accessories");
        Console::WriteLine(L"S - Surge Protector");
        Console::Write(L"Your Choice? ");
        category = __wchar_t::Parse(Console::ReadLine());
        Console::Write(L"Make         ");
        make = Console::ReadLine();
        Console::Write(L"Model:       ");
        model = Console::ReadLine();
        Console::Write(L"Discount Applied (Enter 0 to 100, 0 if no discount): ");
        discount = double::Parse(Console::ReadLine());
        Console::Write(L"Unit Price:  ");
        price = double::Parse(Console::ReadLine());
    
        CStoreItem ^ sItem = gcnew CStoreItem;
        sItem->SetItemNumber(number);
        sItem->SetCategory(category);
        sItem->SetMake(make);
        sItem->SetModel(model);
        sItem->SetDiscountRate(discount);
        sItem->SetUnitPrice(price);
    
        return sItem;
    }
    
    void DescribeStoreItem(CStoreItem ^ %item)
    {
        Console::WriteLine(L"Store Item Description");
        Console::WriteLine(L"Item Number:   {0}", item->GetItemNumber());
        Console::WriteLine(L"Category:      {0}", item->GetCategory());
        Console::WriteLine(L"Make           {0}", item->GetMake());
        Console::WriteLine(L"Model:         {0}", item->GetModel());
        Console::WriteLine(L"Discount Rate: {0:P}", item->GetDiscountRate());
        Console::WriteLine(L"Unit Price:    {0:C}", item->GetUnitPrice());
    }
  7. Execute the application to test it. Here is an example:
     
    To create a store item, enter its information
    Item Number: 204066
    Category
    A - Audio Cables
    B - Batteries
    C - Cellphones and Accessories
    D - Bags and Cases
    H - Headphones
    M - Digital Cameras
    O - Cables and Connectors
    P - PDAs and Accessories
    T - Telephones and Accessories
    S - Surge Protector
    Your Choice? P
    Make         HP
    Model:       iPAQ hw6510 Mobile Messenger
    Discount Applied (Enter 0 to 100, 0 if no discount): 15
    Unit Price:  585.95
    
    =-= Nearson Electonics =-=
    ******* Store Items ******
    Store Item Description
    Item Number:   204066
    Category:      P
    Make           HP
    Model:         iPAQ hw6510 Mobile Messenger
    Discount Rate: 15.00 %
    Unit Price:    $585.95
    
    Press any key to continue . . .
  8. Close the DOS window

Private Methods

As you might have found out, some of the methods of a class are exclusively used to carry assignments. The external functions or other objects don't call such methods and don't communicate with them. If you create a class and know that a particular method is not used to transfer data to the client functions, you can declare such a method as private, just like you would do with a member variable.

To declare a method as private, include it in a private: section of the object. To implement it, follow the same rules we have learned about implementing the methods of an object. You must keep in mind (which will also be very important when we learn about inheritance) is that this method is not available to the outside world. Here is an example:

using namespace System;

public value class CBox
{
private:
	double Length;
	double Height;
	double Width;

public:
	CBox ^ Create();
	void Show();

private:
    double FaceArea()
    {
        return Length * Height;
    }
    double TopArea()
    {
        return Length * Width;
    }

    double  RightArea()
    {
        return Height * Width;
    }
};

CBox ^ CBox::Create()
{
    this->Length = 35.85;
    this->Height = 28.46;
    this->Width  = 22.08;

    return *this;
}

void CBox::Show()
{
    Console::WriteLine(" -=- Box Areas -=-");
    Console::WriteLine("Top:   {0}", this->TopArea());
    Console::WriteLine("Face:  {0}", this->FaceArea());
    Console::WriteLine("Right: {0}", this->RightArea());
}

int main()
{
    CBox ^ box = gcnew CBox;
    CBox ^ one = box->Create();

    one->Show();
    
    Console::WriteLine();
    return 0;
}

Protected Methods

A public method is one that can be accessed outside of its class. A private method is one that cannot be accessed outside of its class. When using inheritance, if you want to create a method that only derived classes can access, put that method in a protected section that is preceded with protected:.

Static Members of a Class

 

Static Member Variables

A class can have static member variables. To declare such a variable, precede it with the static keyword. Here is an example:

public value class CCar
{
private:
    String ^ Make;
    String ^ Model;
    int      Doors;
    int      Year;
    double   Price;
	
public:
    void Build();
    void Show();

    static int Count;
};

When you declare a member variable as static and when the application starts, the compiler creates a copy of that member. This member would be maintained by the compiler while the program is running. If you declare an instance of a class, like the above vehicle variable, the static member is not part of the object: the compiler creates and maintains the static member, whether you use it or not, whether you declare a class variable or not.

In a program, if you use a class that has a static member variable, that member variable is initialize with the minimum value of its type. For example, if the member variable is of an integer type, the static member variable is initialized with 0.

As mentioned already, when a class has a static member variable, you don't need to declare an instance of that class in order to access the static member variable. When the application starts, the member variable is automatically available and you can access it when necessary. You can access it either to retrieve its value or to modify it.

To access a static member of the class outside of that class, enter its data type, followed by the name of the class, followed by the :: operator, followed by the name of the member variable. You can then, for example, retrieve the value of the static member variable. Here is an example:

using namespace System;

public value class CCar
{
private:
    String ^ Make;
    String ^ Model;
    int      Doors;
    int      Year;
    double   Price;
	
public:
    void Build();
    void Show();

    static int Count;
};

void CCar::Build()
{
    Console::WriteLine(L"Enter Car Information");
    Console::Write(L"Enter Make:  ");
    Make = Console::ReadLine();
    Console::Write(L"Enter Model: ");
    Model = Console::ReadLine();
    Console::Write(L"# of Doors:  ");
    Doors = int::Parse(Console::ReadLine());
    Console::Write(L"Year Made:   ");
    Year = int::Parse(Console::ReadLine());
    Console::Write(L"Enter Price: ");
    Price = double::Parse(Console::ReadLine());
}

void CCar::Show()
{
    Console::WriteLine(L"\nCar Characteristics");
    Console::WriteLine(L"Make:  {0}", Make);
    Console::WriteLine(L"Model: {0}", Model);
    Console::WriteLine(L"Doors: {0}", Doors);
    Console::WriteLine(L"Year:  {0}", Year);
    Console::WriteLine(L"Value: {0:C}", Price);
}

int main()
{
    Console::Write("Number of Cars: ");
    Console::WriteLine(CCar::Count);

    Console::WriteLine();
    return 0;
}

Notice that you don't need to declare a variable of a class in order to access a static member variable. The above program produces:

Number of Cars: 0

Press any key to continue . . .

Like the other member variables of a class, you can initialize a static member variable as you see fit. Just remember the rule to access it.

When creating a class, you will decide what member(s) you want to make static and which one(s) will stay regular.

Static Methods

Besides regular member functions, a class can also have static methods. To create a static method, type the static keyword to its left. Here is an example:

public value class CCar
{
private:
    String ^ Make;
    String ^ Model;
    int      Doors;
    int      Year;
    double   Price;
	
public:
    void Build();

    static int  Count;
    static void Display();
};

As mentioned for static member variables, a static method doesn't belong to a particular instance of the class. This means that you don't need to declare a handle of a class in order to access a static method. A static method stands on its own so much that, if you want to access another member of the class, you must declare an instance of that class inside the static method. In other words, the other members of the same class are not automatically accessible from within the static method. As done with the other methods, you can implement a static method outside of the class. If you decide to do this, you must omit the static keyword. Here are examples of static methods:

using namespace System;

public value class CCar
{
private:
    String ^ Make;
    String ^ Model;
    int      Doors;
    int      Year;
    double   Price;
	
public:
    static int  Count;

    static void Build(CCar ^ vehicle);
    static void Display(const CCar ^ car);
};

void CCar::Build(CCar ^ mobile)
{
    Console::WriteLine(L"Enter Car Information");
    Console::Write(L"Enter Make:  ");
    mobile->Make = Console::ReadLine();
    Console::Write(L"Enter Model: ");
    mobile->Model = Console::ReadLine();
    Console::Write(L"# of Doors:  ");
    mobile->Doors = int::Parse(Console::ReadLine());
    Console::Write(L"Year Made:   ");
    mobile->Year = int::Parse(Console::ReadLine());
    Console::Write(L"Enter Price: ");
    mobile->Price = double::Parse(Console::ReadLine());
}

void CCar::Display(const CCar ^ car)
{
    Console::WriteLine(L"\nCar Characteristics");
    Console::WriteLine(L"Make:  {0}", car->Make);
    Console::WriteLine(L"Model: {0}", car->Model);
    Console::WriteLine(L"Doors: {0}", car->Doors);
    Console::WriteLine(L"Year:  {0}", car->Year);
    Console::WriteLine(L"Value: {0:C}", car->Price);
}

int main()
{
    CCar ^ vehicle = gcnew CCar;

    CCar::Build(vehicle);
    CCar::Display(vehicle);

    Console::Write("Number of Cars: ");
    Console::WriteLine(CCar::Count);

    Console::WriteLine();
    return 0;
}

Here is an example of running the program:

Enter Car Information
Enter Make:  Audi
Enter Model: A4 Quattro 3.0 Litre
# of Doors:  4
Year Made:   2003
Enter Price: 25.950

Car Characteristics
Make:  Audi
Model: A4 Quattro 3.0 Litre
Doors: 4
Year:  2003
Value: $25.95
Number of Cars: 0

Press any key to continue . . .

Notice that, inside of main(), you don't need a CCar object (an instance of the CCar class) in order to access the static methods. Also, as mentioned already, you cannot implicitly access the non-static regular members of the class inside of the static method. To access a static member from a static method, you can qualify it. Here is an example:

void CCar::Build(CCar ^ mobile)
{
    Console::WriteLine(L"Enter Car Information");
    Console::Write(L"Enter Make:  ");
    mobile->Make = Console::ReadLine();
    Console::Write(L"Enter Model: ");
    mobile->Model = Console::ReadLine();
    Console::Write(L"# of Doors:  ");
    mobile->Doors = int::Parse(Console::ReadLine());
    Console::Write(L"Year Made:   ");
    mobile->Year = int::Parse(Console::ReadLine());
    Console::Write(L"Enter Price: ");
    mobile->Price = double::Parse(Console::ReadLine());

    CCar::Count++;
}

But you don't have to qualify it: its name would be enough. Here is an example:

using namespace System;

public value class CCar
{
private:
    String ^ Make;
    String ^ Model;
    int      Doors;
    int      Year;
    double   Price;
	
public:
    static int  Count;

    static void Build(CCar ^ vehicle);
    static void Display(const CCar ^ car);
};

void CCar::Build(CCar ^ mobile)
{
    Console::WriteLine(L"Enter Car Information");
    Console::Write(L"Enter Make:  ");
    mobile->Make = Console::ReadLine();
    Console::Write(L"Enter Model: ");
    mobile->Model = Console::ReadLine();
    Console::Write(L"# of Doors:  ");
    mobile->Doors = int::Parse(Console::ReadLine());
    Console::Write(L"Year Made:   ");
    mobile->Year = int::Parse(Console::ReadLine());
    Console::Write(L"Enter Price: ");
    mobile->Price = double::Parse(Console::ReadLine());

    CCar::Count++;
}

void CCar::Display(const CCar ^ car)
{
    Console::WriteLine(L"\nCar Characteristics");
    Console::WriteLine(L"Make:  {0}", car->Make);
    Console::WriteLine(L"Model: {0}", car->Model);
    Console::WriteLine(L"Doors: {0}", car->Doors);
    Console::WriteLine(L"Year:  {0}", car->Year);
    Console::WriteLine(L"Value: {0:C}", car->Price);
    Console::Write("Number of Cars: {0}", Count++);
}

int main()
{
    CCar ^ vehicle = gcnew CCar;

    CCar::Build(vehicle);
    CCar::Display(vehicle);

    Console::WriteLine();
    return 0;
}

Here is an example of running the program:

Enter Car Information
Enter Make:  Jeep
Enter Model: Wrangler Sport
# of Doors:  3
Year Made:   2000
Enter Price: 15500

Car Characteristics
Make:  Jeep
Model: Wrangler Sport
Doors: 3
Year:  2000
Value: $15,500.00
Number of Cars: 1
Press any key to continue . . .

Classes and Constants

 

Static Constants

In C++, you are not allowed to initialize a variable in the body of a class. Consider the following:

#pragma once

namespace Geometry
{
    public ref class CCircle
    {
	public:
        double Radius;
        double Area();

	const double Pi = 3.14159;
    };
}

This class will not compile and you would receive the following error:

error C3845: 'Geometry::CCircle::Pi': 
	only static data members can be initialized 
	inside a ref class or value type

As an alternative, you can declare the variable as a static constant. When creating the constant, you can type the static keyword before or after the data type. Here is an example:

#pragma once

namespace Geometry
{
    public ref class CCircle
    {
	public:
        double Radius;
        double Area();

	static const double Pi = 3.14159;
    };
}

After creating the constant, you can use it as you see fit. To access the constant, you can use it by its name:

#include "circle.h"

namespace Geometry
{
    double CCircle::Area()
    {
	return this->Radius * this->Radius * Pi;
    }
}

You can also access it as you would a static member of a class, using the "::" operator. Here is an example:
Header File: Circle.h
#pragma once

namespace Geometry
{
    public ref class CCircle
    {
	public:
        double Radius;
        double Area();

	static const double Pi = 3.14159;
    };
}
Source File: Circle.cpp
#include "circle.h"

namespace Geometry
{
    double CCircle::Area()
    {
	return this->Radius * this->Radius * CCircle::Pi;
    }
}
Sourcce File: Exercise.cpp
#include "Circle.h"

using namespace System;
using namespace Geometry;

CCircle ^ CreateCircle()
{
    Console::Write(L"Enter the radius of the circle: ");
    CCircle ^ circle = gcnew CCircle;
    circle->Radius = double::Parse(Console::ReadLine());

    return circle;
}

void DescribeCircle(CCircle ^ %round)
{
    Console::WriteLine(L"Circle Description");
    Console::WriteLine(L"Radius: {0:F}", round->Radius);
    Console::WriteLine(L"Area:   {0:F}", round->Area());
}

int main()
{
    CCircle ^ figure = CreateCircle();
    Console::WriteLine();
    DescribeCircle(figure);

    Console::WriteLine();

    return 0;
}

Here is an example of running the program:

Enter the radius of the circle: 48.12

Circle Description
Radius: 48.12
Area:   7274.46

Press any key to continue . . .

Literal Constants

C++/CLI provides an additional way to create a constant in the body of a class. This is done using the literal keyword. Like the const keyword, the literal keyword is followed by the data type, a name for the constant, the assignment operator, the assigned value, and the semi-colon. Here is an example:

#pragma once

namespace Geometry
{
    public ref class CCircle
    {
	public:
        double Radius;
        double Area();

	literal double Pi = 3.14159;
    };
}

After creating the literal constant, you can access it using its name. Here is an example:

#include "circle.h"

namespace Geometry
{
    double CCircle::Area()
    {
	return this->Radius * this->Radius * Pi;
    }
}

You can also qualify its name using the :: operator. This would be done as follows:

#include "circle.h"

namespace Geometry
{
    double CCircle::Area()
    {
	return this->Radius * this->Radius * CCircle::Pi;
    }
}

Like the other member variables, you can create a literal constant in either the public and private sections, and it would follow the rules of that section.

Class Nesting

 

Introduction

A class can be created inside of another class. A class created inside of another is referred to as nested:

Nesting a Class

To nest a class, simply create it as you would any other. Here is an example of a class called Inside that is nested in a class called Outside:

value class Outside
{
	value class Inside
	{
	};
};

In the same way, you can nest as many classes as you wish in another class and you can nest as many classes inside of other nested classes if you judge it necessary. Just as you would manage any other class so can you exercise control on a nested class. For example, you can declare all necessary variables or methods in the nested class or in the nesting class. When you create one class inside of another, there is no special programmatic relationship between both classes:  just because a class is nested doesn't mean that the nested class has immediate access to the members of the nesting class. They are two different classes and they can be used separately. 

The name of a nested class is not "visible" outside of the nesting class. To access a nested class outside of the nesting class, you must qualify the name of the nested class anywhere you want to use it. This is done using the :: operator. For example, if you want to declare an Inside variable somewhere in the program but outside of Outside, you must qualify its name. Here is an example:

using namespace System;

value class COutside
{
public:
	void ShowOutside()
	{
		Console::WriteLine(L"=-= Outside =-=");
	}

	value class CInside
	{
	public:
		void ShowInside()
		{
			Console::WriteLine(L"-=- Inside -=-");
		}
	};
};

int main()
{
    COutside ^ out = gcnew COutside;
    COutside::CInside ^ ins = gcnew COutside::CInside;

    out->ShowOutside();
    ins->ShowInside();

    Console::WriteLine();
    return 0;
}

This would produce:

=-= Outside =-=
-=- Inside -=-

Press any key to continue . . .

Because there is no programmatically privileged relationship between a nested class and its "container" class, if you want to access the nested class in the nesting class, you can use its static members. In other words, if you want, you can declare static all members of the nested class that you want to access in the nesting class. Here is an example:

using namespace System;

value class COutside
{
public:
	void ShowOutside()
	{
		Console::WriteLine(L" =-= Outside =-=");
		CInside::FromInside();
	}

	value class CInside
	{
	public:
		static String ^ InMessage;

		void ShowInside()
		{
			Console::WriteLine(L" -=- Inside -=-");
		}

		static void FromInside()
		{
			CInside::InMessage = L"This is inside";
			Console::WriteLine(CInside::InMessage);
		}
	};
};

int main()
{
    COutside ^ out = gcnew COutside;
    COutside::CInside ^ ins = gcnew COutside::CInside;

    out->ShowOutside();
    ins->ShowInside();

    Console::WriteLine();
    return 0;
}

This would produce:

=-= Outside =-=
This is inside
-=- Inside -=-

Press any key to continue . . .

In the same way, if you want to access the nesting class in the nested class, you can go through the static members of the nesting class. To do this, you can declare static all members of the nesting class that you want to access in the nested class. Here is an example:

using namespace System;

value class COutside
{
public:
	void ShowOutside()
	{
		Console::WriteLine(L"=-= Outside =-=");
		CInside::FromInside();
	}

	static void FromOutside()
	{
		OutMessage = L"This is Outside";
		Console::WriteLine(OutMessage);
	}

	static String ^ OutMessage;

	value class CInside
	{
	public:
		static String ^ InMessage;

		void ShowInside()
		{
			Console::WriteLine(L"-=- Inside -=-");
		}

		static void FromInside()
		{
			CInside::InMessage = L"This is inside";
			Console::WriteLine(CInside::InMessage);
		}

		void ShowOutside()
		{
			COutside::FromOutside();
		}
	};
};

int main()
{
    COutside ^ out = gcnew COutside;
    COutside::CInside ^ ins = gcnew COutside::CInside;

    out->ShowOutside();
    ins->ShowInside();
    out->FromOutside();

    Console::WriteLine();
    return 0;
}

This would produce:

=-= Outside =-=
This is inside
-=- Inside -=-
This is Outside

Press any key to continue . . .

Instead of static members, if you want to access members of a nested class in the nesting class, you can first declare a variable of the nested class in the nesting class. In the same way, if you want to access members of a nesting class in the nested class, you can first declare a variable of the nesting class in the nested class.

Implementing Methods of a Nested Class

In the previous lesson, we saw that C++ allows you to define a method outside of the class by qualifying its name. Here is an example:

value class COutside
{
public:
	void ShowOutside();
};

void COutside::ShowOutside()
{
	Console::WriteLine(L"=-= Outside =-=");
}

To define a method of a nested class outside of the nesting class, you must qualify its name from the parent class. To do this, type the name of the nesting class, followed by ::, followed by the name of the nested class, followed by ::, and followed by the name of the method of the nested class. Here is an example:

using namespace System;

value class COutside
{
public:
	void ShowOutside();

	static void FromOutside()
	{
		Console::WriteLine(L"This is Outside");
	}

	value class CInside
	{
	public:
		void ShowInside();

		static void FromInside()
		{
			Console::WriteLine(L"This is inside");
		}

		void ShowOutside()
		{
			COutside::FromOutside();
		}
	};
};

void COutside::ShowOutside()
{
	Console::WriteLine(L"=-= Outside =-=");
}

void COutside::CInside::ShowInside()
{
	Console::WriteLine(L"-=- Inside -=-");
}

int main()
{
    COutside ^ out = gcnew COutside;
    COutside::CInside ^ ins = gcnew COutside::CInside;

    out->ShowOutside();
    out->FromOutside();
    ins->ShowInside();
    ins->FromInside();

    Console::WriteLine();
    return 0;
}

When implementing a static method globally, remember that you must omit the static keyword:

using namespace System;

value class COutside
{
public:
	void ShowOutside();
	static void FromOutside();

	value class CInside
	{
	public:
		void ShowInside();
		static void FromInside();
	};
};

void COutside::ShowOutside()
{
	Console::WriteLine(L"=-= Outside =-=");
}

void COutside::FromOutside()
{
	Console::WriteLine(L"This is Outside");
}

void COutside::CInside::ShowInside()
{
	Console::WriteLine(L"-=- Inside -=-");
}

void COutside::CInside::FromInside()
{
	Console::WriteLine(L"This is inside");
}

int main()
{
    COutside ^ out = gcnew COutside;
    COutside::CInside ^ ins = gcnew COutside::CInside;

    out->ShowOutside();
    out->FromOutside();
    ins->ShowInside();
    ins->FromInside();

    Console::WriteLine();
    return 0;
}

Previous Copyright © 2006-2016, FunctionX, Inc. Next