Home

Classes and Functions

 

Returning a Class Type

 

Returning a Tracking Reference

As done for regular types, you can return a tracking reference to a class. To indicate this, type the % operator between the class type and the name of the function. In the body of the function, you can create a class as complete as possible, get a tracking reference to that class, and return that reference. Here is an example:

Car
using namespace System;

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

CCar % Build();

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

    Console::WriteLine(L"Car Characteristics");
    Console::WriteLine(L"Make:  {0}", vehicle->Make);
    Console::WriteLine(L"Model: {0}", vehicle->Model);
    Console::WriteLine(L"Doors: {0}", vehicle->Doors);
    Console::WriteLine(L"Year:  {0}", vehicle->Year);
    Console::WriteLine(L"Value: {0:C}", vehicle->Price);

    Console::WriteLine();
    return 0;
}

CCar % Build()
{
    CCar car;

    Console::Write(L"Enter Make:  ");
    car.Make = Console::ReadLine();
    Console::Write(L"Enter Model: ");
    car.Model = Console::ReadLine();
    Console::Write(L"# of Doors:  ");
    car.Doors = int::Parse(Console::ReadLine());
    Console::Write(L"Year Made:   ");
    car.Year = int::Parse(Console::ReadLine());
    Console::Write(L"Enter Price: ");
    car.Price = double::Parse(Console::ReadLine());

    CCar % veh = car;
    return veh;
}

This would produce:

Enter Make:  Honda
Enter Model: Accord
# of Doors:  4
Year Made:   1998
Enter Price: 14500
Car Characteristics
Make:  Honda
Model: Accord
Doors: 4
Year:  1998
Value: $14,500.00

Press any key to continue . . .

Practical LearningPractical Learning: Introducing Data Reading

  1. To start a new program, launch 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 RealEstate10 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 Property and click Add
  8. Complete the file as follows:
     
    #pragma once
    using namespace System;
    
    namespace RealEstate
    {
        public ref class CProperty
        {
        public:
            long PropertyNumber;
            String ^ Address;
            String ^ City;
            String ^ State;
            String ^ ZIPCode;
            int Bedrooms;
            float Bathrooms;
            int YearBuilt;
            double MarketValue;
        };
    }
  9. To create another header file, on the main menu, click Project -> Add New Item...
  10. In the Templates list, make sure Header File (.h) is selected.
    Set the Name to House and press Enter
  11. Complete the file as follows:
     
    #pragma once
    
    #include "Property.h"
    
    using namespace System;
    
    namespace RealEstate
    {
        public ref class CHouse : public CProperty
        {
        public:
            Byte Stories;
            int  Condition;
            unsigned NumberOfGarageSpaces;
        };
    }
  12. To create one more header file, on the main menu, click Project -> Add New Item...
  13. In the Templates list, make sure Header File (.h) is selected.
    Set the Name to SingleFamily and click Add
  14. Complete the file as follows:
     
    #pragma once
    #include "House.h"
    
    using namespace System;
    
    namespace RealEstate
    {
        public ref class CSingleFamily : public CHouse
        {
        public:
            __wchar_t Style;
            double LotSizeInSqFt;
        };
    }
  15. To create a source file, on the main menu, click Project -> Add New Item...
  16. In the Templates list, click C++ File (.cpp)
  17. In the New box, type Exercise and click Add
  18. In the empty file, type:
     
    #include <iostream>
    #include "SingleFamily.h"
    
    using namespace std;
    using namespace RealEstate;
    
    int main()
    {
        String ^ strTitle1 = L"=//= Altair Realty =//=";
        String ^ strTitle2 = L"-=- Properties Inventory -=-";
        CSingleFamily ^ home = gcnew CSingleFamily;    
    
        Console::WriteLine(strTitle1);
        Console::WriteLine(strTitle2);
    
        Console::WriteLine();
        return 0;
    }
  19. Execute the application to test it
  20. Close the DOS window

Returning a Handle

If you are defining a function and you want it to return a handle to a class, you can. To indicate this, between the name of the class and the name of the function, type the ^ operator.

Practical LearningPractical Learning: Returning a Handle

  1. To return a handle, change the Exercise.cpp file as follows:
     
    #include <iostream>
    #include "SingleFamily.h"
    
    using namespace std;
    using namespace RealEstate;
    
    CSingleFamily ^ CreateListing()
    {
        CSingleFamily ^ home = gcnew CSingleFamily;    
    
        Console::WriteLine("To create a listing, enter the following information");
        Console::Write("Property #:    ");
        home->PropertyNumber = long::Parse(Console::ReadLine());
        Console::WriteLine("Property Condition");
        Console::WriteLine("0. Unknown");
        Console::WriteLine("1. Excellent");
        Console::WriteLine("2. Good (may need minor repair");
        Console::WriteLine("3. Acceptable (needs major repair)");
        Console::WriteLine("4. Even (land is more important)");
        Console::Write("Your Choice:    ");
        home->Condition = int::Parse(Console::ReadLine());
        Console::Write("Street Address: ");
        home->Address = Console::ReadLine();
        Console::Write("City:           ");
        home->City = Console::ReadLine();
        Console::Write("State:          ");
        home->State = Console::ReadLine();
        Console::Write("ZIP Code:       ");
        home->ZIPCode = Console::ReadLine();
        Console::Write("Bedrooms:       ");
        home->Bedrooms = int::Parse(Console::ReadLine());
        Console::Write("Bathrooms:      ");
        home->Bathrooms = float::Parse(Console::ReadLine());
        Console::Write("Stories:        ");
        home->Stories = int::Parse(Console::ReadLine());
        Console::Write("Year Built:     ");
        home->YearBuilt = int::Parse(Console::ReadLine());
        Console::WriteLine("Style");
        Console::WriteLine("U. Unknown");
        Console::WriteLine("S. Split Level");
        Console::WriteLine("C. Colonial");
        Console::WriteLine("G. Georgial");
        Console::Write("Your Choice:    ");
        home->Style = __wchar_t::Parse(Console::ReadLine());
        Console::Write("Garage Spaces:  ");
        home->NumberOfGarageSpaces = int::Parse(Console::ReadLine());
        Console::Write("Total Lot Size: ");
        home->LotSizeInSqFt = double::Parse(Console::ReadLine());
        Console::Write("Market Value:   ");
        home->MarketValue = double::Parse(Console::ReadLine());
    
        return home;
    }
    
    int main()
    {
        String ^ strTitle1 = L"=//= Altair Realty =//=";
        String ^ strTitle2 = L"-=- Properties Inventory -=-";
      
        CSingleFamily ^ house = CreateListing();
    
        system("cls");
    
        Console::WriteLine(strTitle1);
        Console::WriteLine(strTitle2);
        Console::WriteLine("=//= Property Listing =//=");
        Console::WriteLine("Property #:    {0}", house->PropertyNumber);
        Console::WriteLine("Address:       {0}\n              {1}, {2} {3}",
    	                house->Address, house->City,
    			house->State, house->ZIPCode);
        Console::WriteLine("Condition:     {0}", house->Condition);
        Console::WriteLine("Style:         {0}", house->Style);
        Console::WriteLine("Bedrooms:      {0}", house->Bedrooms);
        Console::WriteLine("Bathrooms:     {0}", house->Bathrooms);
        Console::WriteLine("Stories:       {0}", house->Stories);
        Console::WriteLine("Year Built:    {0}", house->YearBuilt);
        Console::WriteLine("Garage Spaces: {0} SqFt",
    			house->NumberOfGarageSpaces);
        Console::WriteLine("Lot Size:      {0:F}", house->LotSizeInSqFt);
        Console::WriteLine("Market Value:  {0:C}", house->MarketValue);
    
        Console::WriteLine();
        return 0;
    }
  2. Execute the application to test it
  3. Close the DOS window

Passing a Class Type

 

Passing a Tracking Reference

Like a regular data type, a class can be passed to a function as argument. You can pass an argument as a tracking reference. To do this, in the parentheses of the function, type the name of the class, followed by the % operator, followed by a name for the argument. This would be done as follows:

void DescribeProperty(CHouse % home);

In the body of the function, you can either ignore the argument and not use it at all, or you can process or use the argument as you see fit. At a minimum, you can retrieve the values of its member variables, using the period operator. As mentioned for the regular types, when (only) declaring a function that takes a class type as argument, you can omit the name of the argument.

When calling the function, pass the argument with the * operator. Here is an example:

using namespace System;

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

CCar % Build();
void Show(CCar % car);

int main()
{
    Console::WriteLine(L"Enter Car Information");
    CCar ^ vehicle = Build();

    Console::WriteLine(L"\nCar Characteristics");
    Show(*vehicle);

    Console::WriteLine();
    return 0;
}

CCar % Build()
{
    CCar car;

    Console::Write(L"Enter Make:  ");
    car.Make = Console::ReadLine();
    Console::Write(L"Enter Model: ");
    car.Model = Console::ReadLine();
    Console::Write(L"# of Doors:  ");
    car.Doors = int::Parse(Console::ReadLine());
    Console::Write(L"Year Made:   ");
    car.Year = int::Parse(Console::ReadLine());
    Console::Write(L"Enter Price: ");
    car.Price = double::Parse(Console::ReadLine());

    CCar % veh = car;
    return veh;
}

void Show(CCar % car)
{
    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);
}

In the same way, you can pass as many tracking references as you want to a function.

If a function doesn't modify an argument, you can pass it as a constant. This also applies to tracking references. Here is an example:

using namespace System;

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

CCar % Build();
void Show(const CCar % car);

int main()
{
    Console::WriteLine(L"Enter Car Information");
    CCar ^ vehicle = Build();

    Console::WriteLine(L"\nCar Characteristics");
    Show(*vehicle);

    Console::WriteLine();
    return 0;
}

CCar % Build()
{
    CCar car;

    . . .

    CCar % veh = car;
    return veh;
}

void Show(const CCar % car)
{
    . . .
}

Passing a Handle

Another technique you can use to pass a class by reference is to pass it as a handle. To start with the formula we reviewed, use the ^ operator instead of %. In the body of the function, you can access each member variable using the -> operator.

As mentioned for a tracking reference, if the function doesn't modify the argument, the handle can be passed as a constant. 

Using handles as arguments, you can overload a function by creating functions with the same name with either different types of argument(s) or different numbers of arguments.

Practical LearningPractical Learning: Passing a Handle

  1. To pass a handle as argument, change the Exercise.cpp file as follows:
     
    #include <iostream>
    #include "SingleFamily.h"
    
    using namespace std;
    using namespace RealEstate;
    
    CSingleFamily ^ CreateListing()
    {
        CSingleFamily ^ home = gcnew CSingleFamily;    
    
        Console::WriteLine("To create a listing, "
    			enter the following information");
        Console::Write("Property #:    ");
        home->PropertyNumber = long::Parse(Console::ReadLine());
        Console::WriteLine("Property Condition");
        Console::WriteLine("0. Unknown");
        Console::WriteLine("1. Excellent");
        Console::WriteLine("2. Good (may need minor repair");
        Console::WriteLine("3. Acceptable (needs major repair)");
        Console::WriteLine("4. Even (land is more important)");
        Console::Write("Your Choice:    ");
        home->Condition = int::Parse(Console::ReadLine());
        Console::Write("Street Address: ");
        home->Address = Console::ReadLine();
        Console::Write("City:           ");
        home->City = Console::ReadLine();
        Console::Write("State:          ");
        home->State = Console::ReadLine();
        Console::Write("ZIP Code:       ");
        home->ZIPCode = Console::ReadLine();
        Console::Write("Bedrooms:       ");
        home->Bedrooms = int::Parse(Console::ReadLine());
        Console::Write("Bathrooms:      ");
        home->Bathrooms = float::Parse(Console::ReadLine());
        Console::Write("Stories:        ");
        home->Stories = int::Parse(Console::ReadLine());
        Console::Write("Year Built:     ");
        home->YearBuilt = int::Parse(Console::ReadLine());
        Console::WriteLine("Style");
        Console::WriteLine("U. Unknown");
        Console::WriteLine("S. Split Level");
        Console::WriteLine("C. Colonial");
        Console::WriteLine("G. Georgial");
        Console::Write("Your Choice:    ");
        home->Style = __wchar_t::Parse(Console::ReadLine());
        Console::Write("Garage Spaces:  ");
        home->NumberOfGarageSpaces = int::Parse(Console::ReadLine());
        Console::Write("Total Lot Size: ");
        home->LotSizeInSqFt = double::Parse(Console::ReadLine());
        Console::Write("Market Value:   ");
        home->MarketValue = double::Parse(Console::ReadLine());
    
        return home;
    }
    
    void ShowProperty(const CSingleFamily ^ home)
    {
        Console::WriteLine("=//= Property Listing =//=");
        Console::WriteLine("Property #:    {0}", home->PropertyNumber);
        Console::WriteLine("Address:       {0}\n              {1}, {2} {3}",
    	                   home->Address, home->City,
    			           home->State, home->ZIPCode);
        Console::WriteLine("Condition:     {0}", home->Condition);
        Console::WriteLine("Style:         {0}", home->Style);
        Console::WriteLine("Bedrooms:      {0}", home->Bedrooms);
        Console::WriteLine("Bathrooms:     {0}", home->Bathrooms);
        Console::WriteLine("Stories:       {0}", home->Stories);
        Console::WriteLine("Year Built:    {0}", home->YearBuilt);
        Console::WriteLine("Garage Spaces: {0} SqFt",
    		home->NumberOfGarageSpaces);
        Console::WriteLine("Lot Size:      {0:F}", home->LotSizeInSqFt);
        Console::WriteLine("Market Value:  {0:C}", home->MarketValue);
    }
    
    int main()
    {
        String ^ strTitle1 = L"=//= Altair Realty =//=";
        String ^ strTitle2 = L"-=- Properties Inventory -=-";
      
        CSingleFamily ^ house = CreateListing();
    
        system("cls");
    
        Console::WriteLine(strTitle1);
        Console::WriteLine(strTitle2);
        ShowProperty(house);
    
        Console::WriteLine();
        return 0;
    }
  2. Execute the application and test it. Here is an example:
     
    Screen 1
    To create a listing, enter the following information
    Property #:    530955
    Property Condition
    0. Unknown
    1. Excellent
    2. Good (may need minor repair
    3. Acceptable (needs major repair)
    4. Even (land is more important)
    Your Choice:    3
    Street Address: 7244 Lemson Drive
    City:           Alexandria
    State:          VA
    ZIP Code:       22231
    Bedrooms:       3
    Bathrooms:      1.5
    Stories:        1
    Year Built:     1954
    Style
    U. Unknown
    S. Split Level
    C. Colonial
    G. Georgian
    Your Choice:    S
    Garage Spaces:  0
    Total Lot Size: 5488.82
    Market Value:   388940
    Screen 2
    =//= Altair Realty =//=
    -=- Properties Inventory -=-
    =//= Property Listing =//=
    Property #:    530955
    Address:       7244 Lemson Drive
                  Alexandria, VA 22231
    Condition:     3
    Style:         S
    Bedrooms:      3
    Bathrooms:     1.5
    Stories:       1
    Year Built:    1954
    Garage Spaces: 0 SqFt
    Lot Size:      5488.82
    Market Value:  $388,940.00
    
    Press any key to continue . . .
  3. Close the DOS window

The Effect of Passing a Class as a Tracking Reference or as a Handle

When programming in C++/CLI, most of the time, you use classes as managed types and you pass them to functions as tracking references or as handles. Passing a function as a tracking reference or as a handle has the same effect as passing the argument as a native reference: when the function ends, if it modified the argument, the object would retain its value:

using namespace System;

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

void Build(CCar ^ car);
void Show(const CCar ^ car);
Car
int main()
{
    Console::WriteLine(L"Enter Car Information");
    CCar ^ vehicle = gcnew CCar;
	
    Build(vehicle);

    Console::WriteLine(L"\nCar Characteristics");
    Show(vehicle);

    Console::WriteLine();
    return 0;
}

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

void Show(const CCar ^ car)
{
    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);
}

Here is an example of running the program:

Enter Car Information
Enter Make:  Toyota
Enter Model: Corolla
# of Doors:  4
Year Made:   2000
Enter Price: 12650

Car Characteristics
Make:  Toyota
Model: Corolla
Doors: 4
Year:  2000
Value: $12,650.00

Press any key to continue . . .

This also means that you can pass a class type as a tracking reference or as a handle with the goal of updating it. Again, this also means that you can pass different handles to a function and have that function return more than one value. Remember that if a function modifies the handle, you must not pass it as a constant.

Passing a Handle as a Reference

We saw that, when a function receives a handle as argument, if it modifies the value of that handle, the argument would keep the changes when the function terminates. You can reinforce this by passing the argument as a tracking reference. To do this, enter the % operator between the ^ and the name of the argument. Here is an example:

void Show(CCar ^ %car);

Notice that the space, or lack of it, between both operators, is not important. The compiler will reconcile it when running the application. When using the argument, you can access its member variables using either the period or the arrow operator. Here are both functions implemented:

using namespace System;

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

void Build(CCar ^ %car);
void Show(const CCar ^ car);

int main()
{
    Console::WriteLine(L"Enter Car Information");
    CCar ^ vehicle = gcnew CCar;
	
    Build(vehicle);

    Console::WriteLine(L"\nCar Characteristics");
    Show(vehicle);

    Console::WriteLine();
    return 0;
}

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

void Show(const CCar ^ car)
{
    . . .
}

You can also pass a handle as a native reference by using & instead of %. This can be done as follows:

using namespace System;

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

void Build(CCar ^ &car);
void Show(const CCar ^ car);

int main()
{
    . . .

    Console::WriteLine();
    return 0;
}

void Build(CCar ^ &car)
{
	. . .
}

void Show(const CCar ^ car)
{
    . . .
}

Using the String Class

 

Returning a String

The string is the most regular type of value used in an application. It can be a group of characters or symbol of any kind in any order. To represent it, as mentioned in Lesson 4, the string is represented in the C++/CLI language by the String class. As a managed type, a String object is declared as a handle. This is the same basis you use to involve a String object in a function.

As a managed class, to return a String value from a function, when creating the function, specify that it returns a handle to String. Here is an example:

String ^ GetPropertyAddress();

When implementing the function, in its body, do whatever you want but the rule, as always, is that you must return a string before the closing curly bracket. Here is an example:

using namespace System;

String ^ GetPropertyAddress();

int main()
{
	String ^ adrs = GetPropertyAddress();

	Console::WriteLine(L"\nAddress: {0}", adrs);
	return 0;
}

String ^ GetPropertyAddress()
{
	String ^ strAddress;

	Console::Write(L"Enter Property's Address: ");
	strAddress = Console::ReadLine();

	return strAddress;
}

Here is an example of running the program:

Enter Property's Address: 6802 Lilas Drive

Address: 6802 Lilas Drive
Press any key to continue . . .

A function that returns a string can take any type of argument such as a primitive type.

Passing a String

A String object can be passed to a function. As a managed type, the argument must be passed either as a tracking reference or as a handle. To pass the argument as a handle, follow the rules we reviewed, that is, precede the name of the argument with the ^ operator. Here is an example:

using namespace System;

String ^ GetPropertyAddress();
void ShowAddress(String ^); 

int main()
{
	String ^ adrs = GetPropertyAddress();
	
	ShowAddress(adrs);

	return 0;
}

String ^ GetPropertyAddress()
{
	String ^ strAddress;
	
	Console::Write(L"Enter Property's Address: ");
	strAddress = Console::ReadLine();

	return strAddress;
}

void ShowAddress(String ^ strAdrs)
{
	Console::WriteLine(L"\nAddress: {0}", strAdrs);
}

Here is an example of running the program:

Enter Property's Address: 8804 Acacia Rd

Address: 8804 Acacia Rd
Press any key to continue . . .

In the same way, you can pass as many strings as you judge necessary. Also, you can pass a mix of strings and other primitive types.

Introduction to the Methods of a Class

 

Methods Fundamentals

Like a variable, a function can be made a member of a class. This allows a class to perform its own assignments and/or better manage its behavior. These tasks cannot be handled by a regular member variable. When a function is a member of a class, that function is called a method.

To create a method, you start like a normal function but you include it in the body of the class. Here is an example:

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

In the same way, you can add as many methods as you judge necessary for your class. Here is an example:

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

Practical LearningPractical Learning: Introducing Methods

  1. To start a new project, on the main menu, click File -> New -> Project...
  2. On the left side, make sure that Visual C++ is selected. In the Templates list, click CLR Empty Project
  3. In the Name box, replace the string with ElectroStore1 and click OK
  4. On the main menu, click Project -> Add New Item...
  5. To create a header file, in the Templates list, click Header File (.h)
  6. Set the Name to StoreItem and click Add
  7. Complete the file as follows:
     
    #pragma once
    using namespace System;
    
    namespace ElectronicsStore
    {
        public ref class CStoreItem
        {
        private:
            long        ItemNumber;
            __wchar_t ^ Category;
            String ^    Make;
            String ^    Model;
            double      DiscountRate;
            double      UnitPrice;
        };
    }
  8. To create a source file, in the Templates list, click C++ File (.cpp)
  9. Set the Name to Exercise and click Add
  10. 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 ^ item = gcnew CStoreItem;    
    
        Console::WriteLine(strTitle);
    
        Console::WriteLine();
        return 0;
    }
  11. Execute the application to test it. This would produce:
     
    =-= Nearson Electonics =-=
    ******* Store Items ******
    
    Press any key to continue . . .
  12. Close the DOS window

Method Local Definition

There are at least two techniques you can use to implement a method. To implement a method in the class where the method is declared, use the same techniques we used to define regular functions. When a method is a class' member, it has access to the member variables of the same class; this means that you don't need to pass the variables as arguments; you can just use any of them as if it were supplied. Here is an example:

public value class CCar
{
private:
    String ^ Make;
    String ^ Model;
    int      Doors;
    int      Year;
    double   Price;
	
public:
    void Build()
    {
        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 Show();
};

To call a method from a declared handle of a class, you can use the -> operator just as you would proceed to access a member of a class. 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()
    {
        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());
    }
};

int main()
{
    CCar ^ vehicle = gcnew CCar;
	
    vehicle->Build();

    Console::WriteLine();
    return 0;
}

Practical LearningPractical Learning: Implementing a Method Locally

  1. To implement a method locally, access the StoreItem.h file and create the following method:
     
    #pragma once
    using namespace System;
    
    namespace ElectronicsStore
    {
        public ref class CStoreItem
        {
        private:
            long     ItemNumber;
            __wchar_t ^ Category;
            String ^ Make;
            String ^ Model;
            double   DiscountRate;
            double   UnitPrice;
    
        public:
            void CreateStoreItem()
    	{
    	    Console::WriteLine(L"To create a store item, enter its information");
    	    Console::Write(L"Item Number: ");
    	    ItemNumber = 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 if no discount): ");
    	    DiscountRate = double::Parse(Console::ReadLine());
    	    Console::Write(L"Unit Price:  ");
    	    UnitPrice = double::Parse(Console::ReadLine());
    	}
        };
    }
  2. Save the file

Method Global Definition

Instead of using the body of a class, you can also define a method outside of its class. To do this, start with void or the return type of the method, followed by the name of the class, followed by the :: operator, followed by the name of the method, followed by its parentheses, followed by the body of the method delimited by its curly brackets. The method must have been declared in the body of the class. 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()
    {
        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 Show();
};

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()
{
    CCar ^ vehicle = gcnew CCar;
	
    vehicle->Build();

    vehicle->Show();

    Console::WriteLine();
    return 0;
}

You can use a mixture of local and global method definitions. Make sure that each method is implemented only once, either locally, in the object, or globally, outside of the object.

By tradition, when defined globally, the methods of a class are implemented in the associated source file of the header file of the class.

Practical LearningPractical Learning: Implementing Methods Globally

  1. Change the StoreItem.h header file as follows:
     
    #pragma once
    using namespace System;
    
    namespace ElectronicsStore
    {
        public ref class CStoreItem
        {
        private:
            long        ItemNumber;
            __wchar_t ^ Category;
            String    ^ Make;
            String    ^ Model;
            double      DiscountRate;
            double      UnitPrice;
    
        public:
    	void CreateStoreItem();
    	void ItemDescription();
        };
    }
  2. To create a source file, in the Templates list, click C++ File (.cpp)
  3. Set the Name to StoreItem and click Add
  4. Complete the file as follows:
       
    #include "StoreItem.h"
    using namespace System;
    
    namespace ElectronicsStore
    {
        void CStoreItem::CreateStoreItem()
       {
    	Console::WriteLine(L"To create a store item, enter its information");
    	Console::Write(L"Item Number: ");
    	ItemNumber = 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 if no discount): ");
    	DiscountRate = double::Parse(Console::ReadLine());
    	Console::Write(L"Unit Price:  ");
    	UnitPrice = double::Parse(Console::ReadLine());
        }
    
        void CStoreItem::ItemDescription()
        {
            Console::WriteLine(L"Store Item Description");
    	Console::WriteLine(L"Item Number:   {0}", ItemNumber);
    	Console::WriteLine(L"Category:      {0}", Category);
    	Console::WriteLine(L"Make           {0}", Make);
    	Console::WriteLine(L"Model:         {0}", Model);
    	Console::WriteLine(L"Discount Rate: {0}", DiscountRate);
    	Console::WriteLine(L"Unit Price:    {0}", UnitPrice);
        }
    }
  5. Access the Exercise.cpp file and change it as follows:
     
    #include "StoreItem.h"
    
    using namespace System;
    using namespace ElectronicsStore;
    
    int main()
    {
        String ^ strTitle = L"=-= Nearson Electonics =-=\n"
    		        L"******* Store Items ******";
        CStoreItem ^ item = gcnew CStoreItem;    
    
        item->CreateStoreItem();
        Console::WriteLine();
        Console::WriteLine(strTitle);
        item->ItemDescription();
    
        Console::WriteLine();
        return 0;
    }
  6. Execute the application to test it. Here is an example:
     
    To create a store item, enter its information
    Item Number: 624406
    Category
    A - Audio Cables
    B - Batteries
    C - Cell Phones 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? M
    Make         Canon
    Model:       Powershot A620
    Discount Applied (Enter 0 to 100, 0 if no discount): 20
    Unit Price:  320.95
    
    =-= Nearson Electonics =-=
    ******* Store Items ******
    Store Item Description
    Item Number:   624406
    Category:      M
    Make           Canon
    Model:         Powershot A620
    Discount Rate: 20.00 %
    Unit Price:    $320.95
    
    Press any key to continue . . .
  7. Close the DOS window

Inline Methods

When a method is implemented locally, that is, in the body of a class, it is referred to as inline. To re-enforce this, you can precede its name with the inline keyword when declaring the method in the class. Here is an example:

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

    void Show();
};

If you define a method globally but you want it to be processed as inline, precede its name with the inline keyword. Here is an example:

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

    void Show();
};

void inline 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);
}

You can choose which method(s) would be inline and which one(s) would not. When implementing the method, you can precede the method with the inline keyword. You can also omit the inline keyword in the class but use it when defining the method.

After defining the method of class, whether locally or globally, any method can call another without using an access operator. This allows an class’ methods to exchange information among themselves easily. Furthermore, unlike regular functions where a function must be declared prior to another function calling it, the methods of a class don't follow that rule: one method can call another method before or after the other has been implemented, as long as it is defined somewhere in the program.

Class and Self Return

 

Introduction

When it comes to returning a class after processing it, you have two main alternatives: you can get a class to be returned by an external function or you can create a method that returns its own type of class. To proceed, first declare a method by specifying its return type as the class itself. Because a managed class can only be declared as a handle, the return type must be specified as a handle. Here is an example:

public value class CHouse
{
public:
	__wchar_t TypeOfHome;
	int NumberOfBedrooms;
	double NumberOfBathrooms;
	Byte Stories;
	int YearBuilt;
	double Value;

	CHouse ^ Create();
};

In the body of the method, proceed as you see fit. As done with other functions, before the end of the method, you must remember to return a handle to the class. Here is an example:

CHouse ^ CHouse::Create()
{
    CHouse ^ home = gcnew CHouse;

    home->TypeOfHome = L's';
    home->NumberOfBedrooms = 4;
    home->NumberOfBathrooms = 3.5;
    home->Stories = 2;
    home->YearBuilt = 2002;
    home->Value = 455960;

    return home;
}

After defining a self returning method, you can call it like you would any normal method. Here is an example:

using namespace System;

public value class CHouse
{
public:
	__wchar_t TypeOfHome;
	int NumberOfBedrooms;
	double NumberOfBathrooms;
	Byte Stories;
	int YearBuilt;
	double Value;

	CHouse ^ Create();
	void Show();
};

int main()
{
	CHouse ^ House2002 = gcnew CHouse;
	CHouse ^ Property = House2002->Create();
	Property->Show();

        Console::WriteLine();
	return 0;
}

CHouse ^ CHouse::Create()
{
    CHouse ^ home = gcnew CHouse;

    home->TypeOfHome = L's';
    home->NumberOfBedrooms = 4;
    home->NumberOfBathrooms = 3.5;
    home->Stories = 2;
    home->YearBuilt = 2002;
    home->Value = 455960;

    return home;
}

this Pointer

C++ proposes an alternative to returning a class from one of its methods. Instead of explicitly declaring a variable when implementing a method that returns the same class, the compiler simply needs to know what object you want to return: the object that called the method or a newly declared one. If you want to return the same object, you can use a special pointer called this.

As its name implies, the this pointer is a self referencing object, which means it allows you to designate the object that is making the call as the same object you are referring to. Using the this pointer is a technique that allows you to perform any necessary operation on an object without the help of an external function and returning the same object.

Suppose you want to transform the Create() method of the CHouse class above so it would return the same variable that calls it. Because the method will return the same object, you don't need to declare a local variable to hold the changed variable. Since the member variables of the class will be modified, the method cannot be declared as a constant.

When implementing this method, the values of the variables will certainly be modified to implement whatever behavior you want. To return the same object, the this object must be called as a pointer, with *this. This would be done as follows:

CHouse ^ CHouse::Create()
{
    return *this;
}

One way you can use a method that self-returns its class is to initialize its member variables. Since the method returns its class, you can therefore return a pointer to this. Here is an example:

using namespace System;

public value class CHouse
{
public:
	__wchar_t TypeOfHome;
	int NumberOfBedrooms;
	double NumberOfBathrooms;
	Byte Stories;
	bool HasGarage;
	int YearBuilt;
	double Value;

	CHouse ^ Create();
	void Show();
};

int main()
{
    CHouse ^ House2002 = gcnew CHouse;
    CHouse ^ Property = House2002->Create();
    Property->Show();

    Console::WriteLine();
    return 0;
}

CHouse ^ CHouse::Create()
{
    TypeOfHome        = L'C';
    NumberOfBedrooms  = 1;
    NumberOfBathrooms = 1.0;
    Stories           = 1;
    HasGarage         = false;
    YearBuilt         = 1960;
    Value             = 100000;

    return *this;
}

void CHouse::Show()
{
    . . .
}

Instead of returning a handle, since the method that returns the this pointer returns it as a pointer, you can make it return a tracking reference. Here is an example:

CHouse % CHouse::Create()
{
    TypeOfHome        = L'C';
    NumberOfBedrooms  = 1;
    NumberOfBathrooms = 1.0;
    Stories           = 1;
    HasGarage         = false;
    YearBuilt         = 1960;
    Value             = 100000;

    return *this;
}

This version of the method would produce the same effect as the previous one.

Practical LearningPractical Learning: Using the this Pointer

  1. Access the StoreItem.cpp source file
  2. To use the this pointer, change the members of the class as follows:
     
    #include "StoreItem.h"
    using namespace System;
    
    namespace ElectronicsStore
    {
        void CStoreItem::CreateStoreItem()
       {
    	Console::WriteLine(L"To create a store item, enter its information");
    	Console::Write(L"Item Number: ");
    	this->ItemNumber = 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? ");
    	this->Category = __wchar_t::Parse(Console::ReadLine());
    	Console::Write(L"Make         ");
    	this->Make = Console::ReadLine();
    	Console::Write(L"Model:       ");
    	this->Model = Console::ReadLine();
    	Console::Write(L"Discount Applied (Enter 0 to 100, 0 if no discount): ");
    	this->DiscountRate = double::Parse(Console::ReadLine());
    	Console::Write(L"Unit Price:  ");
    	this->UnitPrice = double::Parse(Console::ReadLine());
        }
    
        void CStoreItem::ItemDescription()
        {
            Console::WriteLine(L"Store Item Description");
    	Console::WriteLine(L"Item Number:   {0}", this->ItemNumber);
    	Console::WriteLine(L"Category:      {0}", this->Category);
    	Console::WriteLine(L"Make           {0}", this->Make);
    	Console::WriteLine(L"Model:         {0}", this->Model);
    	Console::WriteLine(L"Discount Rate: {0:P}", this->DiscountRate / 100);
    	Console::WriteLine(L"Unit Price:    {0:C}", this->UnitPrice);
        }
    }
  3. Execute the application to test it
  4. Close the DOS window

Previous Copyright © 2006 FunctionX, Inc. Next