Lesson Home

Functions and Classes

 

Member Functions of a Class

 

Introduction to Methods

A class is an entity that should be as self sufficient as possible. To achieve this, besides its member variables, a class  ought to carry its own assignment(s), but drawing the line between its role and its valuable interaction with the possible and eventual other objects of the same program.

To carry the assignments that are inherent to the functionality of a class, you add functions to it. Just like variables that are part of a class, a function of a class is referred to as a member of the class. A function that is part of a class is called a method.

 

Declaring Methods

A class' method is declared like a regular function but included in the body of the class. Therefore, to declare a method, provide its return type followed by a name and the required parentheses of every function. To make sure sure that a function is a member of a class, it must be included in its body.

The methods of a class have access to all members of the same class, including members of the private section. This means that the methods of a class can manipulate and even modify the values of the member variables. Also the member variables do not need to be declared in a method. Based on this, you can declare a method as void but use it internally as if it were returning a variable.

Here are examples of methods of a class:

public __gc class CStoreItem
{
public:
    char    ItemNumber;
    char    ItemName;
    double  UnitPrice;
    double  Discount;
    double  CalculateDiscountAmount();
    double  CalculateItemPrice();
};
 

Implementing Methods Locally

There are at least two techniques you can use to define a method of a class. To implement a method in the class where it 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 do not need to pass the variables as arguments. You can just use any of them as if it were declared in the member function. Here is an example of implementing a method in the body of its object:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace std;
using namespace System;

public __gc class CStoreItem
{
public:
    long   ItemNumber;
    double UnitPrice;
    double Discount;
    double CalculateDiscountAmount()
    {
        return UnitPrice * Discount / 100;
    }
    //double CalculateItemPrice();
};

int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CStoreItem *storeItem = new CStoreItem;

    storeItem->ItemNumber = 386454;
    storeItem->UnitPrice  = 34.95;
    storeItem->Discount   = 20; // %
	
    Console::WriteLine("Department Store - Receipt");
    Console::WriteLine("Item #:        {0}",   __box(storeItem->ItemNumber));
    Console::WriteLine("Unit Price:    {0:C}", __box(storeItem->UnitPrice));
    Console::WriteLine("Discount Rate: {0}%",  __box(storeItem->Discount));
    Console::WriteLine("Disc Amt:      {0:C}", __box(storeItem->CalculateDiscountAmount()));

    Console::WriteLine();
    return 0;
}

This would produce:

Department Store - Receipt
Item #:        386454
Unit Price:    $34.95
Discount Rate: 20%
Disc Amt:      $6.99

Press any key to continue
 

Implementing Methods Globally

As opposed to implementing a method in its parent class, you can define it outside of the class. To do this, you must qualify it by typing its return type, followed by the name of the class, followed by the :: operator, then followed by the function and its complete definition.

Here is an example:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace std;
using namespace System;

public __gc class CStoreItem
{
public:
    long   ItemNumber;
    double UnitPrice;
    double Discount;
    double CalculateDiscountAmount()
    {
        return UnitPrice * Discount / 100;
    }
    double CalculateItemPrice();
};

double CStoreItem::CalculateItemPrice()
{
    double discAmount = CalculateDiscountAmount();
    return UnitPrice - discAmount;
}

int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CStoreItem *storeItem = new CStoreItem;

    storeItem->ItemNumber = 386454;
    storeItem->UnitPrice  = 34.95;
    storeItem->Discount   = 20; // %
	
    Console::WriteLine("Department Store - Receipt");
    Console::WriteLine("Item #:        {0}",   __box(storeItem->ItemNumber));
    Console::WriteLine("Unit Price:    {0:C}", __box(storeItem->UnitPrice));
    Console::WriteLine("Discount Rate: {0}%",  __box(storeItem->Discount));
    Console::WriteLine("Disc Amt:      {0:C}", __box(storeItem->CalculateDiscountAmount()));
    Console::WriteLine("Net Price:     {0:C}", __box(storeItem->CalculateItemPrice()));

    Console::WriteLine();
    return 0;
}

This would produce:

Department Store - Receipt
Item #:        386454
Unit Price:    $34.95
Discount Rate: 20%
Disc Amt:      $6.99
Net Price:     $27.96

Press any key to continue

 

Object Construction

  

Method Initializer

We saw that, when declaring a variable of an object, this declaration gives life to the object. When such an object is instantiated, the compiler reserves enough memory space for each member of the class. Still, as we saw with regular variables, the memory space for each member variable of the object is filled with 0. Consider the following program:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

public __gc class CRectangle
{
private:
    double length;
    double height;
public:
    double Perimeter();
    double Area();
    void   ShowCharacteristics();
};

double CRectangle::Perimeter()
{
    return 2 * (length + height);
}

double CRectangle::Area()
{
    return length * height;
}

void CRectangle::ShowCharacteristics()
{
    Console::WriteLine("Rectangle Characteristics");
    Console::WriteLine("Length:    {0}", __box(length));
    Console::WriteLine("Width:     {0}", __box(height));
    Console::WriteLine("Perimeter: {0}", __box(Perimeter()));
    Console::WriteLine("Area:      {0}", __box(Area()));
}
	
int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CRectangle *rect = new CRectangle;

    rect->ShowCharacteristics();

    Console::WriteLine();
    return 0;
}

This would produce:

Rectangle Characteristics
Length:    0
Width:     0
Perimeter: 0
Area:      0

Press any key to continue

One way you can predict the values of an object is to provide a particular method whose role would be used to initialize its member variables. A method that initializes an object can return any value but it is preferable to be of type void because its primary purpose is to reset the values. Since this method would give a starting value to all member variables that need to be initialized, it should have an equivalent argument for each of the member variables that it initializes. Such a method can be declared as follows:

public __gc class CRectangle
{
private:
    double length;
    double height;
public:
    void   Initializer(double L, double H);
    double Perimeter();
    double Area();
    void   ShowCharacteristics();
};

The method initializer does not have to initialize all members of the object. To implement such a method, simply assign each one of its arguments to the corresponding member variable of the object. Here is an example:

void CRectangle::Initializer(double L, double H)
{
    length = L;
    height = H;
}

Having a method initializer, you can call it after you have declared the instance of the object to give it initial values. Here is an example:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

public __gc class CRectangle
{
private:
    double length;
    double height;
public:
    void   Initializer(double L, double H);
    double Perimeter();
    double Area();
    void   ShowCharacteristics();
};

void CRectangle::Initializer(double L, double H)
{
    length = L;
    height = H;
}

double CRectangle::Perimeter()
{
    return 2 * (length + height);
}

double CRectangle::Area()
{
    return length * height;
}

void CRectangle::ShowCharacteristics()
{
    Console::WriteLine("Rectangle Characteristics");
    Console::WriteLine("Length:    {0}", __box(length));
    Console::WriteLine("Width:     {0}", __box(height));
    Console::WriteLine("Perimeter: {0}", __box(Perimeter()));
    Console::WriteLine("Area:      {0}", __box(Area()));
}
	
int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CRectangle *rect = new CRectangle;

    rect->Initializer(25.55, 20.85);
    rect->ShowCharacteristics();

    Console::WriteLine();
    return 0;
}

An example of running the program would produce: 

Rectangle Characteristics
Length:    25.55
Width:     20.85
Perimeter: 92.8
Area:      532.7175

Press any key to continue
  

The Default Constructor

A constructor is a special method that is created when an object is created or defined. This particular method holds the same name as that of the class and it initializes the instance of the class whenever an object is created. The constructor also usually holds the initializations of the different declared member variables of its class. Unlike some of the other methods, the constructor does not return a value, not even void.

When you create an object, if you don't declare a constructor, the compiler would create one for you. This is useful because it lets all other objects and functions of the program know that this object exists. This compiler-created constructor is called the default constructor. If you want to create your own constructor, simply add a method with the same name as the object. Here is an example:

public __gc class CRectangle
{
private:
    double length;
    double height;
public:
    CRectangle();
    void   Initializer(double L, double H);
    double Perimeter();
    double Area();
    void   ShowCharacteristics();
};

When you declare an instance of an object, whether you use that object or not, a constructor for the object is created and signals itself. When an instance of an object has been declared, the default constructor is called, whether the object is used or not. This is illustrated in the following program:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

public __gc class CRectangle
{
public:
    CRectangle();
};

CRectangle::CRectangle()
{
    Console::WriteLine("Here is a new rectangle");
}
	
int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CRectangle *rect = new CRectangle;

    Console::WriteLine();
    return 0;
}

This would produce:

Here is a new rectangle
Press any key to continue

As you can see, even though the rect variable was not used, just its declaration was enough to signal it. You might find it sometimes convenient to create your own constructor because, whether you create an empty constructor or not, this does not negatively impact your program but makes it more lively and allows other parts of the program to conveniently call the object using its constructor.

When declaring an instance of an object using the default constructor, you can use or omit the parentheses. The effect is the same. Therefore, you can declare a CRectangle variable as follows:

CRectangle *Rect = new CRectangle();
 

The Constructor as a Method Initializer

A constructor can be used to initialize the member variables of an object. As such, a constructor provides a valuable alternative to a method initializer, the type of method we saw earlier. To use a constructor to initialize the member variables of an object, provide as arguments the necessary variables that you intend to initialize. You don't have to initialize all member variables in the constructor, only those that need to be initialized. In fact, you should initialize only those members that you think the other objects or functions would need to provide when calling this object. This means that your object may have member variables that, either the external objects or functions don't need to modify (or access) or the member variable(s) will be initialized later when called from the needed object(s) or function(s).

To implement a default constructor, you can just initialize the desired members of the object. For a member variable of a numeric type, you can just assign the desired constant to each. Here is an example:

public __gc class CRectangle
{
private:
    double  Length;
    double  Width;
public:
    CRectangle();
};

CRectangle::CRectangle()
{
    Length = 0.00;
    Width  = 0.00;
}

 

Constructor Overloading

As seen above, the default constructor is the favorite place to provide default values to the members of an object. Besides the default constructor, you can add as many constructors as you judge necessary. This feature of C++ allows you to create various constructors for different reasons. This also means that, like ordinary functions, the methods or constructors of an object can be overloaded.

One of the rules of function overloading consists of having functions with different types of arguments. The most basic constructor you would create can use a single argument. Such a constructor can be declared as follows:

__gc class CRectangle
{
private:
    double Length;
    double Width;
public:
    CRectangle();
    CRectangle(double Len);
};

When implementing a constructor that takes one argument, you should initialize the member that corresponds to the unique argument and initialize the other members with default values. Here is an example:

CRectangle::CRectangle(double Len)
{
    Length = Len;
    Width  = 0.00;
}

In this case, when declaring an instance of the object, you can provide one value in the constructor. When declaring a variable, if you don't provide a value, the default constructor may be called. Otherwise, you can declare a variable with a value. The value must be the same type as one of the constructors. In the same way, you can create different constructors for different initializations. Here is an example:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

public __gc class CRectangle
{
private:
    double length;
    double height;
public:
    CRectangle();
    CRectangle(double Len);
    CRectangle(double Len, double Hgt);
    double Perimeter();
    double Area();
    void   ShowCharacteristics();
};

CRectangle::CRectangle()
{
    length = 0.00;
    height = 0.00;
}

CRectangle::CRectangle(double Len)
{
    length = Len;
    height = 0.00;
}

CRectangle::CRectangle(double L, double H)
{
    length = L;
    height = H;
}

double CRectangle::Perimeter()
{
    return 2 * (length + height);
}

double CRectangle::Area()
{
    return length * height;
}

void CRectangle::ShowCharacteristics()
{
    Console::WriteLine("Rectangle Characteristics");
    Console::WriteLine("Length:    {0:F}", __box(length));
    Console::WriteLine("Width:     {0:F}", __box(height));
    Console::WriteLine("Perimeter: {0:F}", __box(Perimeter()));
    Console::WriteLine("Area:      {0:F}", __box(Area()));
}
	
int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CRectangle *rect = new CRectangle();
    rect->ShowCharacteristics();
    Console::WriteLine();

    rect = new CRectangle(25.55);
    rect->ShowCharacteristics();
    Console::WriteLine();

    rect = new CRectangle(25.55, 20.75);
    rect->ShowCharacteristics();

    Console::WriteLine();
    return 0;
}

This would produce:

Rectangle Characteristics
Length:    0.00
Width:     0.00
Perimeter: 0.00
Area:      0.00

Rectangle Characteristics
Length:    25.55
Width:     0.00
Perimeter: 51.10
Area:      0.00

Rectangle Characteristics
Length:    25.55
Width:     20.75
Perimeter: 92.60
Area:      530.16

Press any key to continue

If you create different constructors with different arguments to initialize (remember the rules of function overloading), when declaring these objects, make sure you initialize each instance with the right number of arguments; otherwise, the compiler may complain.

If you create an object and create it with only one constructor, if you create this constructor with at least one argument, the default constructor would not be available anymore.

Therefore, if you want to access a default constructor of an object, you have two alternatives:

  • If you don't create any constructor at all on an object, the default constructor would always be available whenever you invoke that object.
  • If you create at least one constructor on an object and supply at least one argument to that constructor, you must explicitly create a default constructor for your object.
 

Techniques of Initializing With a Constructor

We saw that methods can be implemented inline, that is, in the body of a class. This also applies to constructors:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

public __gc class CTriangle
{
private:
    double base;
    double height;
public:
    CTriangle();
    CTriangle(double b, double h);
    double Area();
    void   ShowCharacteristics();
};

CTriangle::CTriangle()
{
    base   = 0.00;
    height = 0.00;
}

CTriangle::CTriangle(double b, double h)
{
    base   = b;
    height = h;
}

double CTriangle::Area()
{
    return base * height / 2;
}

void CTriangle::ShowCharacteristics()
{
    Console::WriteLine("Triangle Characteristics");
    Console::WriteLine("Base:   {0:F}", __box(base));
    Console::WriteLine("Height: {0:F}", __box(height));
    Console::WriteLine("Area:   {0:F}", __box(Area()));
}

int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CTriangle *triangle1 = new CTriangle();
    triangle1->ShowCharacteristics();
    Console::WriteLine();

    CTriangle *triangle2 = new CTriangle(32.05, 26.48);
    triangle2->ShowCharacteristics();

    Console::WriteLine();
    return 0;
}

This would produce:

Triangle Characteristics
Base:   0.00
Height: 0.00
Area:   0.00

Triangle Characteristics
Base:   32.05
Height: 26.48
Area:   424.34

Press any key to continue

Keep in mind that the constructors could also be implemented inline as follows:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

public __gc class CTriangle
{
private:
    double base;
    double height;
public:
    CTriangle() { base = 0.00; height = 0.00 }
    CTriangle(double b, double h) { base = b, height = h; }
    double Area();
    void   ShowCharacteristics();
};

double CTriangle::Area()
{
    return base * height / 2;
}

void CTriangle::ShowCharacteristics()
{
    Console::WriteLine("Triangle Characteristics");
    Console::WriteLine("Base:   {0:F}", __box(base));
    Console::WriteLine("Height: {0:F}", __box(height));
    Console::WriteLine("Area:   {0:F}", __box(Area()));
}

int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CTriangle *triangle1 = new CTriangle();
    triangle1->ShowCharacteristics();
    Console::WriteLine();

    CTriangle *triangle2 = new CTriangle(32.05, 26.48);
    triangle2->ShowCharacteristics();

    Console::WriteLine();
    return 0;
}

C++ provides another technique you can use to initialize the member variables in a constructor. To initialize the list of members, after defining the constructor, which is after the parentheses, type a colon, followed by the name of an argument and include the initial value in parentheses. The initializations are separated by a comma. Since the constructor is a method, make sure you provide its body. Here is an example:

 
public __gc class CTriangle
{
private:
    double base;
    double height;
public:
    CTriangle() : base(0.00), height(0.00) { }
    CTriangle(double b, double h) : base(b), height(h) { }

    double Area();
    void   ShowCharacteristics();
};

You can use the same technique to initialize other constructors if more than one.

If you don't want to implement the constructors in the body of the class, you can carry them globally, using the same syntax. Here is an example

public __gc class CTriangle
{
private:
    double base;
    double height;
public:
    CTriangle();
    CTriangle(double b, double h);

    double Area();
    void   ShowCharacteristics();
};

CTriangle::CTriangle()
    : base(0.00), height(0.00)
{
}

CTriangle(double b, double h)
    : base(b), height(h)
{
}
 

this Pointer

 

Classes and Functions

 

Introduction

Consider a CCone class created as follows:

#pragma once

public __gc class CCone
{
private:
    double radius;
    double height;
public:
    CCone();
    CCone(double r, double h);
    double BaseArea();
    double LateralArea();
    double TotalArea();
    double Volume();
};

The class could be implemented as follows:

#include "StdAfx.h"
#include ".\cone.h"
#using <mscorlib.dll>

using namespace System;

CCone::CCone(void)
    : radius(0.00), height(0.00)
{
}

CCone::CCone(double r, double h)
    : radius(r), height(h)
{
}

double CCone::BaseArea()
{
    return radius * radius * Math::PI;
}

double CCone::LateralArea()
{
    // The area covered by the tissue that covers the tent
    double radius2 = radius * radius;
    double height2 = height * height;
    double slantHeight = Math::Sqrt(radius2 + height2);
    return Math::PI * radius * slantHeight;
}

double CCone::TotalArea()
{
    return BaseArea() + LateralArea();
}

double CCone::Volume()
{
    return (Math::PI * radius * radius * height) / 3;
}

After creating such a class, it becomes a valid type, sometimes referred to as a programmer-defined data type. As such, you can declare an object inside of a function and use it. That is what we have done so far when using objects inside of the _tmain() function:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"
#include "Cone.h"

#using <mscorlib.dll>

using namespace std;
using namespace System;

int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CCone *Conic = new CCone;
    double R, H;

    Console::WriteLine("Enter the cone's dimensions");
    Console::Write("Radius: ");
    cin >> R;
    Console::Write("Height: ");
    cin >> H;

    Conic = new CCone(R, H);

    Console::WriteLine("\nCone's Characteristics");
    Console::WriteLine("Base Area:    {0}", __box(Conic->BaseArea()));
    Console::WriteLine("Total Area:   {0}", __box(Conic->TotalArea()));
    Console::WriteLine("Texture Area: {0}", __box(Conic->LateralArea()));

    Console::WriteLine();
    return 0;
}

Here is an example of running the program:

Enter the cone's dimensions
Radius: 24.75
Height: 20.42

Cone's Characteristics
Base Area:    1924.4218498646
Total Area:   4419.28343664751
Texture Area: 2494.86158678291

Press any key to continue

As opposed to processing an object from the _tmain() function, you can use an external function to take care of such an assignment so that when the object is returned, other functions of the program can use its characteristics.

 

An Object as a Return Value

As a data type, you can use a class as a return value of a function. When returning an object, you should be familiar with the construction of the object, especially its constructor(s). Since you will mostly return an object as complete as possible, the returned variable is a constructor. Therefore, when using the object inside of a function, make sure that the object can be used as a variable.

Here is an example:

// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"
#include "Cone.h"

#using <mscorlib.dll>

using namespace std;
using namespace System;

CCone* RequestDimensions();

int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CCone *Conic = new CCone;

    Conic = RequestDimensions();

    Console::WriteLine("\nCone's Characteristics");
    Console::WriteLine("Base Area:    {0}", __box(Conic->BaseArea()));
    Console::WriteLine("Total Area:   {0}", __box(Conic->TotalArea()));
    Console::WriteLine("Texture Area: {0}", __box(Conic->LateralArea()));

    Console::WriteLine();
    return 0;
}

CCone *RequestDimensions()
{
    double R, H;

    Console::WriteLine("Enter the cone's dimensions");
    Console::Write("Radius: ");
    cin >> R;
    Console::Write("Height: ");
    cin >> H;

    CCone *cone = new CCone(R, H);
    return cone;
}

An example of running the program would produce:

Enter the cone's dimensions
Radius: 32.68
Height: 28.04

Cone's Characteristics
Base Area:    3355.1656620032
Total Area:   7776.08936218447
Texture Area: 4420.92370018128

Press any key to continue

 

An Object as Argument

One of the most regular operations you will perform in your program consists of mixing objects and functions. Fortunately, C++ allows you to pass an object to a function or to return an object from a function. An object you use in a program can come from any source: an object built-in the operating system (part of the Win32 library), an object shipped with the Managed C++ compiler, or one that you create.

You can pass a member of a class as argument to a function, or you can pass the whole object. When passing a class as argument, you should be familiar with the construction of the class, know its members and which ones you need to use. The code completion feature is highly useful in this circumstance.

To pass an object as argument, type its name and the name of the argument in the parentheses of the function. For example, instead of displaying the characteristics of the CCone variable in the _tmain() function, we can use an external function to perform that assignment. To do this, we would pass a CCone as argument. Here is an example:

  
// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"
#include "Cone.h"

#using <mscorlib.dll>

using namespace std;
using namespace System;

CCone* RequestDimensions();
void ShowCharacteristics(CCone *c);

int _tmain()
{
    // TODO: Please replace the sample code below with your own.
    CCone *Conic = new CCone;

    Conic = RequestDimensions();
    ShowCharacteristics(Conic);

    Console::WriteLine();
    return 0;
}

CCone *RequestDimensions()
{
    double R, H;

    Console::WriteLine("Enter the cone's dimensions");
    Console::Write("Radius: ");
    cin >> R;
    Console::Write("Height: ");
    cin >> H;

    CCone *cone = new CCone(R, H);
    return cone;
}

void ShowCharacteristics(CCone* cone)
{
    Console::WriteLine("\nCone's Characteristics");
    Console::WriteLine("Base Area:    {0}", __box(cone->BaseArea()));
    Console::WriteLine("Total Area:   {0}", __box(cone->TotalArea()));
    Console::WriteLine("Texture Area: {0}", __box(cone->LateralArea()));
}

Here is an example of executing the program:

Enter the cone's dimensions
Radius: 42.08
Height: 35.64

Cone's Characteristics
Base Area:    5562.9010497575
Total Area:   12852.9298464062
Texture Area: 7290.02879664875

Press any key to continue

Even if you let the user provide the values of the object, after constructing such an object, you can pass it to a function that would manipulate it, including displaying its characteristics.

 

 

Previous Copyright © 2004-2010 FunctionX, Inc. Next