Fundamentals of Structures

Introduction

So far, when we needed a value, we declared a variable for it. If we needed another value, we declared another variable. Sometimes, the variables you are using in a program describe the same thing, with each variable providing a separate piece of information. A structure is a teachnique to group some variables that have a common goal, such as to provide pieces of information for one object.

Practical LearningPractical Learning: Introducing Structures

  1. Start Microsoft Visual Studio
  2. Create a new Console App named RoadSystemDatabase1

Creating a Structure

To let you create a structure, bothe the C and the C++ languages provide a keyword named struct. The primary formula to create a structure is:

struct name{};

Therefore, to create a structure, start with the strut keyword. Add a name. The name follows the rules we reviewed for names of variables; there will be some variations and we will point them out. After the name of the structure, create a body delimited by curly brackets. End the creation with a semicolon. Here is an example:

struct Employee{};

To make your code easy to read, you can spread the body to different lines. Here is an example:

struct Employee
{
};

Creating an Object

When you have created a structure, it becomes a data type like those we have used so far. Therefore, to use a structure, you can declare a variable of it. You have many options. You can declare the variable using the techniques we applied with the other types so far. This means that, outside the structure, you can type the name of the structure, a space, and a name for the variable. Here is an example of declaring a variable of a structure:

struct Employee
{
    
};

int main()
{
    Employee empl;
}

As another technique, when declaring the variable, precede the name of the structure with the strut keyword. Here is an example:

struct Employee
{
    
};

int main()
{
    strut Employee empl;
}

When you have declared a variable of a structure type, you are said to have created an object. You are also said to have created an instance of the structure.

Practical LearningPractical Learning: Creating a Structure

Introduction to the Members of a Structure

Adding a Member Variable to a Structure

In the body of a structure, you can declare one or more variables. A variable declared in the body of a structure is referred to as a member variable. You declare the variable the same way we have done so far. Here is an example:

struct Employee
{
    int YearlySalary;
};

Accessing a Member of an Object

To access a member of a structure, you use the period operator. after declaring a variable of that structure, (on another line,) type the name of that variable, a period, and the desired member variable of the structure. This can be done as follows:

struct Employee
{
    int YearlySalary;
};

int main()
{
    Employee empl;

    empl.YearlySalary . . .
}

Initializing a Member of a Structure

By default, a member of a variable doesn't automatically have a value. As we have seen with other data types so far, before using a member variable of a struture, that member variable must have a valid value. There are various ways you can specify the value of a member variable. The primary way is to assign a value to the member variable when declaring that member. Here is an example:

struct Vehicle { double Price = 24688; };

As another technique, if you have declaring a variable for the struction, after accessing a member variable of that structure, you can simply assign a value to it. Here is an example:

struct Employee
{
    int YearlySalary;
};

int main()
{
    Employee empl;

    empl.YearlySalary = 55885;
}

When you have provided the values of the member variables of a structure, you are said to have defined or described the object.

A Global Object

Just as reviewed for variables of primitive types, if you create an object inside of a function, which is referred to as a local declaration, the object can be accessed only from that function. If you want an object to be accessible to more than one function, you can declare it outside of any function. This is a global declaration. To proceed, you would use the same approach as the global declaration of a primitive type. Here is an example:

struct Employee
{
    int YearlySalary;
};

Employee staff;

int main()
{
    Employee empl;

    empl.YearlySalary = 55885;
}

Once again, it is important to know that the compiler works from top-down. If you declare a variable globally, it can be "seen" only by functions under it. Based on this, in the above example, you can access the animal variable from the main() function. Consider the following:

#include <iostream>
using namespace std;

struct Foot
{
    int numberOfFingers;
};

Foot animal;

int main()
{
    struct Foot human;
}

Foot bird;

In this case, you can access animal from the main() function but you cannot access bird from main().

If you declare a variable of a structure outside a function, such as outside the main() function, and we called it a global object, if you need to assign a value to a member variable of the structure, you must perform that operation in a function that is below the declared variable. Here is an example:

struct Employee
{
    int YearlySalary;
};

Employee staff;

int main()
{
    staff.YearlySalary = 112600;
    
    Employee empl;

    empl.YearlySalary = 55885;
}

Adding Member Variables to a Structure

In the above example, we added only one member variable to a structure. In the same way, in the body of a structure, you can declare as many variables as you judge neccessary. After declaring a variable of that structure, you can access each member variable using the period operator as we saw for one member variable.

Practical LearningPractical Learning: Adding a Field to a Structure

  1. In the body of the structure, create some member variables as follows:
    struct Road
    {
        string Designation;
        double Distance;
        string Start;
        string End;
    };
    
    
            public string Designation { get; set; }
            Category RoadType { get; set; }
        double Distance{ get; set; }
        string Start { get; set; }
        string End { get; set; }
  2. Click the Program.cs tab and change the document as follows:
    using static System.Console;
    using RoadSystemDatabase1;
    
    Road rd = new Road();
    rd.Designation = "I-83";
    rd.Distance = 85.3;
    rd.Start = "East Fayette Street / North President Street / Fallsway in Baltimore, MD";
    rd.End = "I-81 / US 322 / Capital Beltway in Harrisburg, PA";
    
        cout << "Road System Database" << endl;
        cout << "=====================================================================================" << endl;
        cout << "Road Name: " << rd.Designation);
        cout << "Length:    {0} miles", rd.Distance);
        cout << "Start:     " << rd.Start);
        cout << "End:       " << rd.End);
        cout << "=====================================================================================" << endl;
  3. To execute the application to see the result, on the main menu, click Debug -> Start Without Debugging:
    Road System Database
    =====================================================================================
    Road Name: I-83
    Length:    85.3 miles
    Start:     East Fayette Street / North President Street / Fallsway in Baltimore, MD
    End:       I-81 / US 322 / Capital Beltway in Harrisburg, PA
    =====================================================================================
    
    Press any key to close this window . . .
  4. Return to your programming environment, press Enter

Structures and Methods

Introduction

Like a class, a structure can have one or more methods. A structure supports all concepts we reviewed for methods of classes.

Returning a Value from a Method

As see with classes, a method of a structure can be made to return a value of a primitive type. Everything is done as seen with methods of a class. If a method doesn't return an explicit value, you must make it return void. Here is an example:

struct Integer
{
    int Value;

    void Read()
    {
    }
};

Practical LearningPractical Learning: Adding a Method to a Structure

  1. To create a method, type the following code:
    struct Road
    {
        string Designation;
        double Distance;
        string Start;
        string End;
    
            public double GetDistanceInKilometers()
            {
                return Distance * 1.6093;
            }
        }
    };
  2. Click the Program.cs tab and change the document as follows:
    using static System.Console;
    using RoadSystemDatabase1;
    
    Road rd = new Road();
    rd.Designation = "I-83";
    rd.Distance = 85.3;
    rd.Start = "East Fayette Street / North President Street / Fallsway in Baltimore, MD";
    rd.End = "I-81 / US 322 / Capital Beltway in Harrisburg, PA";
    
        cout << "Road System Database" << endl;
        cout << "=====================================================================================" << endl;
        cout << "Road Name: " << rd.Designation);
        cout << "Length:    {0} miles, {1} kilometers", rd.Distance, rd.GetDistanceInKilometers());
        cout << "Start:     " << rd.Start);
        cout << "End:       " << rd.End);
        cout << "=====================================================================================" << endl;
  3. To execute the application to see the result, on the main menu, click Debug -> Start Without Debugging:
    Road System Database
    =====================================================================================
    Road Name: I-83
    Length:    85.3  miles, 137.27329 kilometers
    Start:     East Fayette Street / North President Street / Fallsway in Baltimore, MD
    End:       I-81 / US 322 / Capital Beltway in Harrisburg, PA
    =====================================================================================
    
    Press any key to close this window . . .
  4. Return to your programming environment, press Enter

A Method with Arguments

A method of a structure can use one or more parameters. A method can be overloaded with various versions that take different parameters.

Structures and Constructors

Introduction

As seen with classes, a constructor is a method that holds the same name as its structure and doesn't return a value.

A Default Constructor

As seen with classes, a default constructor is the simplest type of constructor a structure can have. To create a default constructor, simply add a method that is marked with the public keyword, doesn't return a value, and has the name of the structure. Here is an example:

struct Toilet
{
    public Toilet()
    {
    }
};

In the body of the structure, if you want, you can initialize the fields and/or properties of the structure.

Practical LearningPractical Learning: Adding a Method to a Structure

Parameterized Constructors

As seen with a class, you can create a constructor that uses one or more parameters in a structure. The constructors of a structure follow the same rules and suggestions of constructors of a class. Here is an example:

struct Integer
{
    Integer(int number)
    {
        val = number;
    }
    
    int Value;
};

After creating a constructor that uses a parameter, you can declare a variable from it. Pass the (number of required) argument(s). Here is an example:

struct Integer
{
    Integer(int number)
    {
        val = number;
    }
};

Integer itg = new Integer(1257);

A constructor can be overloaded with various versions that use different parameters. Here is an example:

struct Integer
{
    Integer(int number)
    {
        val = number;
    }
    
    Integer(string number)
    {
        val = int.Parse(number);
    }
    
    Integer(int number, int maximumSize)
    {
        val = number;
        maximumSize = 1;
    }
    
    int Value;
};

The Absence of a Default Constructor

In both a class and a structure, you have the option to create or omit a default constructor, a constructor that doesn't take a parameter. In either type, if you don't create any constructor, the compiler implicitly creates a constructor behind-the-scenes. On the other hand, you can explicitly create a default constructor for either type. Here are examples:

class DigitalCamera
{
    double Price { get; set; }

    DigitalCamera()
    {
    }
};

struct Perfume
{
    double Price { get; set; }

    public: Perfume()
    {
    }
};

Remember that, after creating such a default contructor, you can create objects. In either a class or a structure, you can omit a default constructor but create one or more constructors that take(s) at least one parameter. Remember that, in a class, you can omit creating a default constructor but create a constructor that takes at least one constructor. If you do that, the default constructor of a class disappears. As a result, if you create an object using the default constructor, you would receive an error. As a result, the following code produces an error:

DigitalCamera dc = new DigitalCamera();

class DigitalCamera
{
    double Price { get; set; }

    DigitalCamera(double price)
    {
        Price = price;
    }
};

struct Perfume
{
    double Price { get; set; }

    public: Perfume(double price)
    {
        Price = price;
    }
};

One of the differences between a class and a structure is that a structure always has a default constructor. Therefore, if you omit creating a default constructor in a structure, the compiler always implicitly create one and you can use it. As a result, the following code works:

using static System.Console;

/* Uisng an implicit constructor
 * that was not created in the structure. */
Machine mach = new Machine();

mach.ItemCode     = 239_740;
mach.Manufacturer = "Bernette";
mach.Model        = "33";

    cout << "Sewing Others" << endl;
    cout << "=======================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "-----------------------" << endl;
    cout << "Road Name: " << mach.ItemCode << endl;
    cout << "Length:    " << mach.Manufacturer << endl;
    cout << "Start:     " << mach.Model << endl;
    cout << "=======================" << endl;

struct Perfume
{
    double Price { get; set; }

    public:
    Perfume(double price)
    {
        Price = price;
    }
};

struct Machine
{
    private int _code;
    private string _company;
    private string _id;

    public Machine(int code, string make, string model)
    {

    }

    int ItemCode;
    string Manufacturer;
    string Model;
};

Sewing Machine

This would produce:

Sewing Others
=======================
Machine Characteristics
-----------------------
Road Name: 239740
Length:    Bernette
Start:     33
=======================

Press any key to close this window . . .

Primary Constructors

As seen with classes, structures support primary constructors. As a reminder, to create a primary constructor, add parentheses to the name of the structure you are creating. For a simple primary constructor, you can leave the parentheses empty. Here is an example:

Perfume perf = new Perfume();

perf.Price = 145.85;

    cout << "Perfume Characteristics" << endl;
    cout << "-----------------------" << endl;
    cout << "Price: " << perf.Price);
    cout << "=======================" << endl;

struct Perfume()
{
    double Price { get; set; }
}

You can add one or more parameters to the primary constructor. One of the reasons you may want to create a primary constructor is to make the user initialize the structure-based object from the variable, then have read-only properties in the structure. Each of those properties can then be used to simply produce its value. Here is an example of such a scenario:

using static System.Console;

Machine mach = new Machine(285_079, "Brother", "XR3774", 164.88);

    cout << "Sewing Others" << endl;
    cout << "=======================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "-----------------------" << endl;
    cout << "Item Code:  " << mach.ItemCode << endl;
    cout << "Make:       " << mach.Make << endl;
    cout << "Model:      " << mach.Model << endl;
    cout << "Unit Price: " << mach.UnitPrice << endl;
    cout << "=======================" << endl;

struct Perfume()
{
    double Price { get; set; }
}
internal struct Machine(int code, string company, string model, double price)
{
    string Model;
    int ItemCode;
    string Make;
    double UnitPrice;
}

Sewing Machine

This would produce:

Sewing Others
=======================
Machine Characteristics
-----------------------
Item Code:  285079
Make:       Brother
Model:      XR3774
Unit Price: 164.88
=======================

Press any key to close this window . . .

Reading Only from a Structure

Initializing a Structural Object at Startup

Remember that you can create a class or a structure with completely defined (read-write) properties that don't need a constructor to specify their values. This can be done as follows:

using static System.Console;

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Price:        $" << mach.UnitPrice);
    cout << "==============================" << endl;

struct Machine
{
    int ItemCode;
    string Make;
    string Model;
    double UnitPrice;
};

An object created from such a class or structure is referred to as uninitialized. If you don't specify the values of the properties, the compiler will refer to the default value that the (C#) language provides to the data type and the compiler will use that default value. As a result, the above program produces:

Sewing Others
==============================
Machine Characteristics
------------------------------
Item Code:    0
Make:         
Model:        
Price:        $0
==============================

Press any key to close this window . . .

To specify the value of a property, you can access it from the object and assign the desired value to it. This can be done as follows:

Machine mach = new Machine();

mach.ItemCode = 938_074;
mach.Make = "KPCB";
mach.Model = "Serger";
mach.UnitPrice = 172.25;

On the other hand, you may want the user (the programmer) to initialize the object when the variable is created. One way to do this is to replace the desired set clause with the init keyword. Add a parameterized constructor to the (class or) structure. In that constructor, initialize the init property with the corresponding parameter. When creating an object, you must pass the desired value of the property to the parentheses of the object. This can be done as follows:

using static System.Console;

Machine mach = new Machine(938_074, "KPCB", "Serger", 172.25);

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Price:        $" << mach.UnitPrice);
    cout << "==============================" << endl;

struct Machine
{
    int ItemCode;
    string Make;
    string Model;
    double UnitPrice;

    Machine(int code, string make, string model, double price)
    {
        _code = code;
        _make = make;
        _model = model;
        _price = price;
    }
};

Sewing Machine

This would produce:

Sewing Others
==============================
Machine Characteristics
------------------------------
Item Code:    938074
Make:         KPCB
Model:        Serger
Price:        $172.25
==============================

Press any key to close this window . . .

Making a Field or a Property Only Read

Like a class, a structure can have fields or properties that are read-only. As a reminder, to create a read-only field or property, precede it with the readonly keyword. You should initialize that member in a (the) constructor(s) of the structure. After doing that, you can access the read-only property and its value, inside and outside the structure. Here is an example:

#include <iostream>
using namespace std;

Machine mach = new Machine();

mach.Model = "MKR45";
mach.ItemCode = 392_474;
mach.Make = "MILLEPUNTI ";

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Power Source: " << mach.PowerSource);
    cout << "==============================" << endl;

mach = new Machine(947_582);
mach.Model = "ST371HD";
mach.Make = "Brother";

    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Power Source: " << mach.PowerSource);
    cout << "==============================" << endl;

struct Machine
{
    private string _id;
    private int _code;
    private string _company;

    public readonly string PowerSource;

    public Machine()
    {
        PowerSource = "Ac/Dc";
    }

    public Machine(int code)
    {
        ItemCode = code;
        PowerSource = "Corded Electric";
    }

    int ItemCode;
    string Make;
    string Model;
};

This would produce:

Sewing Others
==============================
Machine Characteristics
------------------------------
Item Code:    392474
Make:         MILLEPUNTI
Model:        MKR45
Power Source: Ac/Dc
==============================
Machine Characteristics
------------------------------
Item Code:    947582
Make:         Brother
Model:        ST371HD
Power Source: Corded Electric
==============================

Press any key to close this window . . .

A Structure to Only Read Values

You may remember that when you are creating an object from a class or a structure, you can require the user (programmer) to specify the values of the object in the constructor. In this case, you can create a parameter for each property in a constructor of the class or structure. Here is an example:

using static System.Console;

Machine mach = new Machine(368_374, "Singer", "4411", 148.79);

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Price:        $" << mach.UnitPrice);
    cout << "==============================" << endl;

struct Machine
{
    public Machine(int code, string make, string model, double price)
    {
        ItemCode  = code;
        Make      = make;
        Model     = model;
        UnitPrice = price;
    }

    int ItemCode;
    string Make;
    string Model;
    double UnitPrice;
};

This would produce:

Sewing Others
==============================
Machine Characteristics
------------------------------
Item Code:    368374
Make:         Singer
Model:        4411
Price:        $148.79
==============================

Press any key to close this window . . .

Of course, to change the values of the object, the user can initialize the object with another instance that uses the new operator. This can be done as follows:

Machine mach = new Machine(368_374, "Singer", "4411", 148.79);

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Price:        $" << mach.UnitPrice);
    cout << "==============================" << endl;

mach = new Machine(938_049, "ArtLak", "ArtLak", 58.68);

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Price:        $" << mach.UnitPrice);
    cout << "==============================" << endl;

To reinforce this concept, you can create a read-only structure. To do this, when creating the structure, precede it with the readonly keyword.

using static System.Console;

Machine mach = new Machine(368_374, "Singer", "4411", 148.79);

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Price:        $" << mach.UnitPrice);
    cout << "==============================" << endl;

mach = new Machine(938_049, "ArtLak", "ArtLak", 58.68);

    cout << "Sewing Others" << endl;
    cout << "==============================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "------------------------------" << endl;
    cout << "Item Code:    " << mach.ItemCode);
    cout << "Make:         " << mach.Make);
    cout << "Model:        " << mach.Model);
    cout << "Price:        $" << mach.UnitPrice);
    cout << "==============================" << endl;

struct Machine
{
    public Machine(int code, string make, string model, double price)
    {
        ItemCode  = code;
        Make      = make;
        Model     = model;
        UnitPrice = price;
    }

    int ItemCode;
    string Make;
    string Model;
    double UnitPrice;
};

This would produce:

Sewing Others
==============================
Machine Characteristics
------------------------------
Item Code:    368374
Make:         Singer
Model:        4411
Price:        $148.79
==============================
Sewing Others
==============================
Machine Characteristics
------------------------------
Item Code:    938049
Make:         ArtLak
Model:        ArtLak
Price:        $58.68
==============================

Press any key to close this window . . .
==========================================================================================

Structures and Value Types

Structures and Enumerations

An enumeration can be involved with a structure. The typical way is to create a field that is of an enumeration type. Here is an example:

public enum Category { Highway, Interstate }

struct Road
{
    Category cat;
};

In the same way, you can create a property of the type of an enumeration. You can then use the property like we learned for classes.

Practical LearningPractical Learning: Using an Enumeration

  1. In the Solution Explorer, right-click Models -> Add -> Class...
  2. Change the name to Category
  3. Click Add
  4. To create an enumeration, change the document as follows:
    enum Category
        {
            Regular,
            StateHighway,
            USHighway,
            Interstate,
            Beltway
        }
    }
  5. In the Solution Explorer, right-click Models -> Add -> Class...
  6. Change the name to Road
  7. Press Enter
  8. Change the class as follows:
    struct Road
    {
        Category cat;
    
        Road()
        {
            len       = 0.00;
            id        = "";
            ending    = "";
            beginning = "";
            cat       = Category.Regular;
        }
    
        Road(string identification)
            {
                len       = 0.00;
                ending    = "";
                beginning = "";
                id        = identification;
                cat = Category.Regular;
            }
    
        Road(string identification, double length)
            {
                ending    = "";
                len       = length;
                beginning = "";
                id        = identification;
                cat = Category.Regular;
            }
    
        string Designation;
    
            Category RoadType
            {
     { return cat;  }
     { cat = value; }
            }
    
        double Distance;
        string Start;
        string End;
    
            double GetDistanceInKilometers()
            {
                return Distance * 1.6093;
            }
        }
    }
  9. In the Solution Explorer, right-click Program.cs and click Rename
  10. Type RoadSystemDatabase (to get RoadSystemDatabase.cs) and press Enter twice
  11. Change the document as follows:
    using static System.Console;
    
    using RoadSystemDatabase1
    
    Road rd = new Road();
    rd.Designation = "I-83";
    
    // Roads Categories: Regular, Beltway, Interstate, US Highway, State Highway
    rd.RoadType = Category.Interstate;
    
    rd.Distance = 85.3;
    rd.End = "I-81 / US 322 / Capital Beltway in Harrisburg, PA";
    rd.Start = "East Fayette Street / North President Street / Fallsway in Baltimore, MD";
    
        cout << "Road System Database" << endl;
        cout << "=====================================================================================" << endl;
        cout << "Road Name: " << rd.Designation);
    
        cout << "Road Type: " << rd.RoadType);
    
        cout << "Start:     " << rd.Start);
        cout << "End:       " << rd.End);
        cout << "Length:    {0} miles, {1} kilometers", rd.Distance, rd.GetDistanceInKilometers());
        cout << "=====================================================================================" << endl;
  12. To execute the project, press Ctrl + F5
    Road System Database
    =====================================================================================
    Road Name: I-83
    Start:     East Fayette Street / North President Street / Fallsway in Baltimore, MD
    End:       I-81 / US 322 / Capital Beltway in Harrisburg, PA
    Road Type: Interstate
    Length:    85.3  miles, 137.27329 kilometers
    =====================================================================================
    
    Press any key to close this window . . .
  13. To close the window and return to your programming environment, press E

Structures and Functions or Methods

A Parameter of a Structure Type

You can create a parameter of a function or method and make that parameter a structure type. When calling the function or method, make sure you pass an appropriate object. Here is an example:

using static System.Console;

Machine mach = new Machine(239_740, "Bernette", "b33", (16, 14, 8), 255.55);

// Calling the function
Present(mach);

// Creating a parameter of a structure type
void Present(Machine machine)
{
    cout << "Sewing Others" << endl;
    cout << "===========================================================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "-----------------------------------------------------------" << endl;
    cout << "Item Code:                " << machine.ItemCode);
    cout << "Make:                     " << machine.Make);
    cout << "Model:                    " << machine.Model);
    cout << "Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
               machine.Dimensions.width, machine.Dimensions.height, machine.Dimensions.depth);
    cout << "Price:                   $" << machine.UnitPrice);
}

    cout << "===========================================================" << endl;

struct Machine
{
    int ItemCode;
    string Make;
    string Model;
    double UnitPrice;
    int Width;
    int Height;
    int Depth;

    Machine(int code,
                     string make,
                     string model,
                    int width, int height, int depth,
                     double price)
    {
        (ItemCode, Make, Model, Dimensions, UnitPrice) = (code, make, model, dim, price);
    }
}

Returning a Structured Object from a Function or Method

Like a regular data type or a class, a structure can serve as the return type of a function or a method. The rules are more related to those of a class. When creating the method, type the name of the structure on the left side of the name of the method. In the body of the method, implement the desired behavior. Before exiting the method, make sure you return a valid value that is of the type of the structure.

When a method returns a value of the type of a structure, you can assign the method call to a variable of the type of the structure. Here is an example:

using static System.Console;

Machine Create()
{
    Machine m = new Machine(239_740, "Bernette", "b33", (16, 14, 8), 255.55);

    return m;
}

void Present(Machine machine)
{
    cout << "Sewing Others" << endl;
    cout << "===========================================================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "-----------------------------------------------------------" << endl;
    cout << "Item Code:                " << machine.ItemCode);
    cout << "Make:                     " << machine.Make);
    cout << "Model:                    " << machine.Model);
    cout << "Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
               machine.Dimensions.width, machine.Dimensions.height, machine.Dimensions.depth);
    cout << "Price:                   $" << machine.UnitPrice);
}

Machine product = Create();

Present(product);

    cout << "===========================================================" << endl;

struct Machine
{
    int ItemCode;
    string Make;
    string Model;
    double UnitPrice;
    int Width;
    int Height;
    int Depth;

    Machine(int code,
                     string make,
                     string model,
                    (int width, int height, int depth) dim,
                     double price)
    {
        (ItemCode, Make, Model, Dimensions, UnitPrice) = (code, make, model, dim, price);
    }
};

Practical LearningPractical Learning: Using a Structure Object

  1. Click the ReadSystemDatabase.cs tab and change the document as follows:
    using static System.Console;
    using RoadSystemDatabase;
    
    // Returning a structural object from a function
    Road Create()
    {
        Road rd = new Road();
    
        rd.Distance = 232.406;
        rd.Designation = "US 36";
        rd.RoadType = Category.USHighway;
        rd.End = "US-36 on CO-KS border";
        rd.Start = "Deer Ridge - US 34";
    
        return rd;
    }
    
    // Passing a structural object as argument
    void Show(object obj)
    {
        if (obj is null)
            return;
    
        Road rd = (Road)obj;
    
        cout << "Road System Database" << endl;
        cout << "============================================" << endl;
        cout << "Road Name: " << rd.Designation);
        cout << "Road Type: " << rd.RoadType);
        cout << "--------------------------------------------" << endl;
        cout << "Start:     " << rd.Start);
        cout << "End:       " << rd.End);
        cout << "Length:    {0:N} miles ({1:N} kilometers)", rd.Distance, rd.GetDistanceInKilometers());
        cout << "============================================" << endl;
    }
    
    Road rd = Create();
    Show(rd);
  2. To execute, on the main menu, click Debug -> Start Without Debugging:
    Road System Database
    ============================================
    Road Name: US 36
    Road Type: USHighway
    --------------------------------------------
    Start:     Deer Ridge - US 34
    End:       US-36 on CO-KS border
    Length:    232.41 miles (374.01 kilometers)
    ============================================
    
    Press any key to close this window . . .
  3. Press Z to close the window and return to your programming environment

Structures with Structures and Classes

A Field of a Structure Type

Once a structure exists, you can use it as a type. In a structure or a class, you can create a field that is of a structure type. There is nothing significant to do when declaring the variable. Probably the most important detail to keep in mind is that you must initialize the variable before using it. Here are examples:

using static System.Console;

Triangle tri = new Triangle();

    cout << "Geometry" << endl;
    cout << "=================================" << endl;
    cout << "Triangle Characteristics" << endl;
    cout << "---------------------------------" << endl;
tri.Present();
    cout << "---------------------------------" << endl;
    cout << "Distance 1:  " << tri.Distance1);
    cout << "Distance 2:  " << tri.Distance2);
    cout << "Distance 3:  " << tri.Distance3);
    cout << "=================================" << endl;

struct Point
{
    int X { get; set; }
    int Y { get; set; }
}

class Triangle
{
    private Point point1;
    private Point point2;
    private Point point3;

    Triangle()
    {
        point1 = new Point();
        point1.X = 2;
        point1.Y = 3;

        point2 = new Point();
        point2.X = 4;
        point2.Y = 2;

        point3 = new Point();
        point3.X = 3;
        point3.Y = 6;
    }

    double Distance1
    {

        {
            return Math.Sqrt( ((point2.X - point1.X) * (point2.X - point1.X)) +
                              ((point2.Y - point1.Y) * (point2.Y - point1.Y)) );
        }
    }

    double Distance2
    {

        {
            return Math.Sqrt( ((point3.X - point2.X) * (point3.X - point2.X)) +
                              ((point3.Y - point2.Y) * (point3.Y - point2.Y)) );
        }
    }

    double Distance3
    {

        {
            return Math.Sqrt( ((point1.X - point3.X) * (point1.X - point3.X)) +
                              ((point1.Y - point3.Y) * (point1.Y - point3.Y)) );
        }
    }

    public void Present()
    {
        cout << "Point A({0}, {1})", point1.X, point1.Y);
        cout << "Point B({0}, {1})", point2.X, point2.Y);
        cout << "Point C({0}, {1})", point3.X, point3.Y);
    }
}

This would produce:

Geometry
=================================
Triangle Characteristics
---------------------------------
Point A(2, 3)
Point B(4, 2)
Point C(3, 6)
---------------------------------
Distance 1:  2.23606797749979
Distance 2:  4.123105625617661
Distance 3:  3.1622776601683795
=================================

Press any key to close this window . . .

A Property of a Structure Type

In a structure or a class, you can create a property that is a structure type. The rules are the same we reviewed for creating a property of a class. Here are examples:

using static System.Console;

Triangle tri = new Triangle();

tri.A = new Point(0, 2);
tri.B = new Point(7, 1);
tri.C = new Point(1, -1);

    cout << "Geometry" << endl;
    cout << "=================================" << endl;
    cout << "Triangle Characteristics" << endl;
    cout << "---------------------------------" << endl;
tri.Present();
    cout << "---------------------------------" << endl;
    cout << "Distance 1:  " <<  tri.Distance1);
    cout << "Distance 2:  " << tri.Distance2);
    cout << "Distance 3:  " << tri.Distance3);
    cout << "=================================" << endl;

struct Point
{
    int X { get; set; }
    int Y { get; set; }

    Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

class Triangle
{
    private Point a;
    private Point b;
    private Point c;

    // A property of a structure type
    public Point A
    {

        {
            return a;
        }


        {
            a = value;
        }
    }

    // A property of a structure type
    public Point B
    {

        {
            return b;
        }


        {
            b = value;
        }
    }

    // A property of a structure type
    public Point C
    {

        {
            return c;
        }


        {
            c = value;
        }
    }

    double Distance1
    {

        {
            return Math.Sqrt( ((B.X - A.X) * (B.X - A.X)) +
                              ((B.Y - A.Y) * (B.Y - A.Y)) );
        }
    }

    double Distance2
    {

        {
            return Math.Sqrt( ((C.X - B.X) * (C.X - B.X)) +
                              ((C.Y - B.Y) * (C.Y - B.Y)) );
        }
    }

    double Distance3
    {

        {
            return Math.Sqrt( ((A.X - C.X) * (A.X - C.X)) +
                              ((A.Y - C.Y) * (A.Y - C.Y)) );
        }
    }

    public void Present()
    {
        cout << "Point A({0}, {1})", A.X, A.Y);
        cout << "Point B({0}, {1})", B.X, B.Y);
        cout << "Point C({0}, {1})", C.X, C.Y);
    }
}

    public Road Road1 { get; set; }
    public Road Road2 { get; set; }
    public string InOrNear { get; set; }

    public Intersection()
    {
    }

    public Intersection(Road one, Road two, string position)
    {
        Road1 = one;
        Road2 = two;
        InOrNear = position;
    }
}

After creating the property, you can use it as you see fit.

Structures and Inheritance

A structure is sealed from inheritance. This means that, when it comes to inheritance, a structure is subject to the following characteristics:

Structures and References

Passing a Structural Object by Reference

When you create a parameter in a method or a function and that parameter is a structure type, the technique is referred to as passing by value. A copy of the value of the structure is passed to the method or function. If the function or method modifies the argument, the original value would stay intact. If you want the function or method to modify the value of the structure, you can pass the argument by reference. You can do this using the (rules of the) ref keyword. Here is an example:

using static System.Console;

void Create(ref Machine sew)
{
    sew = new Machine(239_740, "Bernette", "b33", (16, 14, 8), 255.55);
}

void Present(Machine machine)
{
    cout << "Sewing Others" << endl;
    cout << "===========================================================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "-----------------------------------------------------------" << endl;
    cout << "Item Code:                " << machine.ItemCode);
    cout << "Make:                     " << machine.Make);
    cout << "Model:                    " << machine.Model);
    cout << "Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
               machine.Dimensions.width, machine.Dimensions.height, machine.Dimensions.depth);
    cout << "Price:                   $" << machine.UnitPrice);
}

Machine product = new();

Create(ref product);

Present(product);

    cout << "===========================================================" << endl;

struct Machine
{
    int ItemCode { get; init; }
    string Make { init; get; }
    string Model { get; init; }
    double UnitPrice { init; get; }
    (int width, int height, int depth) Dimensions { get; init; }

    Machine(int code,
                     string make,
                     string model,
                    (int width, int height, int depth) dim,
                     double price)
    {
        (ItemCode, Make, Model, Dimensions, UnitPrice) = (code, make, model, dim, price);
    }
}

You can also pass the referenced argument using the out keyword. Here is an example:

using static System.Console;

void Create(out Machine sew)
{
    sew = new Machine(239_740, "Bernette", "b33", (16, 14, 8), 255.55);
}

void Present(Machine machine)
{
    cout << "Sewing Others" << endl;
    cout << "===========================================================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "-----------------------------------------------------------" << endl;
    cout << "Item Code:                " << machine.ItemCode);
    cout << "Make:                     " << machine.Make);
    cout << "Model:                    " << machine.Model);
    cout << "Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
               machine.Dimensions.width, machine.Dimensions.height, machine.Dimensions.depth);
    cout << "Price:                   $" << machine.UnitPrice);
}

Machine product;

Create(out product);

Present(product);

    cout << "===========================================================" << endl;

struct Machine
{
    int ItemCode { get; init; }
    string Make { init; get; }
    string Model { get; init; }
    double UnitPrice { init; get; }
    (int width, int height, int depth) Dimensions { get; init; }

    Machine(int code,
                     string make,
                     string model,
                    (int width, int height, int depth) dim,
                     double price)
    {
        (ItemCode, Make, Model, Dimensions, UnitPrice) = (code, make, model, dim, price);
    }
}

A Referenced Structure

When creating a structure, you can indicate to the compiler that you want the objects created from that structure to be treated as reference type. To do this, before the struct keyword, type the ref keyword. Here is an example:

using static System.Console;

Machine Create()
{
    Machine m = new Machine((15.3, 12.0, 5.80), 162.88);
    
    m.ItemCode = 293_749;
    m.Model = "XR3774";
    m.Make = "Brother";

    return m;
}

void Present(Machine machine)
{
    cout << "Sewing Others" << endl;
    cout << "==============================================================" << endl;
    cout << "Machine Characteristics" << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << "Item Code:                " << machine.ItemCode);
    cout << "Make:                     " << machine.Make);
    cout << "Model:                    " << machine.Model);
    cout << "Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
               machine.Dimensions.width, machine.Dimensions.height, machine.Dimensions.depth);
    cout << "Price:                   $" << machine.UnitPrice);
}

Machine product = Create();

Present(product);

    cout << "==============================================================" << endl;

internal ref struct Machine
{
    private string _id;
    private int _code;
    private string _company;

    public Machine((double width, double height, double depth) dim, double price)
    {
        Dimensions = dim;
        UnitPrice = price;
    }

    int ItemCode
    {

        {

        }


        {
;
        }
    }

    string Make
    {

        {

        }


        {
;
        }
    }

    string Model
    {

        {
            return _id;
        }


        {
;
        }
    }

    (double width, double height, double depth) Dimensions
    {
;
;
    }

    double UnitPrice
    {
;
;
    }
}

This would produce:

Sewing Others
==============================================================
Machine Characteristics
--------------------------------------------------------------
Item Code:                293749
Make:                     Brother
Model:                    XR3774
Dimensions (W x H x D):   15.3 inches x 12 inches x 5.8 inches
Price:                   $162.88
==============================================================

Press any key to close this window . . .

Notice that it is very simple to transform a regular structure into a referenced one. But once you apply that keyword, the structure becomes subject to new rules:

A Read-Only Referenced Structure

When creating a referenced structure, if you want the properties of the structure to be read-only, before the ref struct expression, type the readonly keyword. Here is an example:

// . . .

internal readonly ref struct Machine
{
    // . . .
}
====================================================================

Access to a Member of a Class

After declaring a variable based on a class, you can access its member variables, outside of the class, either to change their value or to retrieve the values they hold. To access the member of a class outside of the class, after declaring it, type the name of the variable, followed by a period, and followed by the name of the member you want to access. For example, to access the NumberOfFingers member variable of a class called Hand using its object instance called human, you would write:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Hand

{

    int numberOfFingers;

};



int Hand;



int main( int argc, char * argv[] )

{

    struct Hand human ;

    

    human.numberOfFingers;



    return 0;

}

It is important to know that you cannot access a member variable while declaring a variable of the class. For example, the following code will not work:

Hand human.NumberOfFingers;

You must first declare the variable followed by its semi-colon. Then access the member variable. After accessing a member of a class, one of the operations you can perform would consist of assigning it a variable, which is referred to as initializing it. In C++, a member of a class cannot be initialized inside of the class. The member would be initialized outside of the class. Here is an example that assigns a value to a member variable of a class:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Hand

{

    int numberOfFingers;

};



int Hand;



int main( int argc, char * argv[] )

{

    struct Hand human ;



    human.NumberOfFingers = 5;



    return 0;

}

In the same way, you can use the period operator to access the member variable of a class and retrieve its value. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Hand

{

    int numberOfFingers;

};



int Hand;



int main( int argc, char * argv[] )

{

    struct Hand human ;



    Hand = 4;

    human.numberOfFingers = 5;



    cout << "Hand    = " << Hand << endl;

    cout << "Fingers = " << human.numberOfFingers;



    return 0;

}

Just as done for variables of built-in types, you can declare as many variables as you see fit in your program. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Foot

{

        int NumberOfToes;

};



int main( int argc, char * argv[] )

{

    Foot human;

    Foot animal;



    return 0;

}

You can also declare various variables on the same line, separated by commas. Here are examples:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>



using namespace std;



class Foot

{

        int NumberOfToes;

};



int main( int argc, char * argv[] )

{

    Foot human, duck, dog, hen;



    return 0;

}
 

Type-Defining a Class

Just as you can type-define the name of a built-in data type, you can do the same for any class. As reviewed for primitive types, when doing this, remember that you are not creating a new type: you are only providing a pseudo-name for an existing class. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Hand

{

  int numberOfFingers;

};



int main( int argc, char * argv[] )

{

    typedef Hand BodyMember;



    return 0;

}

After type-defining a class, you can use the new name to declare a variable as if you were using the actual name of the class. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Hand

{

  int numberOfFingers;

};



int main( int argc, char * argv[] )

{

    typedef Hand BodyMember;



    BodyMember human;

    return 0;

}

Remember that you can also type-define a class' name globally, that is, outside of any function, and use it in the other functions that would need the new name:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Hand

{

  int numberOfFingers;

};



typedef Hand BodyMember;



int main( int argc, char * argv[] )

{

    BodyMember human;

    return 0;

}
 

Class Forward Definition 

Sometimes when creating a class, you may already know the member(s) you want it to have. In some cases, you may want to first communicate the name of the class but you are not ready to list its members. C++ allows you to perform what is referred to a forward definition. In this case, you specify only the type (struct or class) and the name of the class. This allows you to do some tasks that don't require the members of the class. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Hand;

typedef Hand BodyMember;



// Do anything here



int main( int argc, char * argv[] )

{

    return 0;

}

Once you are ready, you can then complete the class as you see fit. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Hand;

typedef Hand BodyMember;



// Do anything here



class Hand

{

    int numberOfFingers;

};



int main( int argc, char * argv[] )

{

    BodyMember human;



    return 0;

}

If you use this technique, you still must define the class before you are able to use it. Consider the following code:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Hand;

typedef Hand BodyMember;



// Do anything here



int main( int argc, char * argv[] )

{

    BodyMember human;



    return 0;

}



class Hand

{

    int numberOfFingers;

};

This code will not compile because, at the time the class is instantiated in main(), its definition is not known, only its emptiness, which is not enough.

The Access Levels of a Class

So far, to make our learning process easier, we declared only one member variable in a class. The primary reason for using a class as opposed to a built-in data type is to be able to group different characteristics used to describe the class and make it as complete as possible. This means that a class is meant to have as many members as you judge necessary. To apply this, in the body of the class, declare the necessary variables, each with a data type and a name, and each declaration ending with a semi-colon. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

        int      Year;

        unsigned NumberOfDoors;

        long     Mileage;

        char     DrivingCondition;

};



int main( int argc, char * argv[] )

{

    return 0;

}

Once again, to access its members outside of the class, you can first declare a variable based on the class. To access a member variable, you type the class' variable name, followed by the period operator. Here is an example:

#include <iostream>

using namespace std;



struct Car

{

	int      Year;

	unsigned NumberOfDoors;

	long     Mileage;

	char     DrivingCondition;

};



int main()

{

	Car vehicle;



	vehicle.Mileage = 42580;



	cout << "Car Characteristics\n";

	cout << "Mileage:   " << vehicle.Mileage << endl;



	return 0;

}

This would produce:

Car Characteristics

Mileage:   42580

A common object in real life is visibly made of two categories of parts: those you can see or touch and those you do not have access to. The parts you can see or touch are considered visible or accessible. In C++, such parts are referred to as public. Those you cannot see or touch are considered hidden. In C++, such parts are referred to as private. Like objects in real life, a class is made of sections that the other parts or other objects cannot “see” and those the other objects can access. The other objects of of the program are sometimes referred to as the clients of the object. The parts the client of an object can touch in a class are considered public and the others are private.

When creating a class, you will define which items are public and which ones are private. The items that are public are created in a section that starts with the public keyword followed by a semi-colon. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

public:

        int      Year;

        unsigned NumberOfDoors;

        long     Mileage;

        char     DrivingCondition;

};



int main( int argc, char * argv[] )

{

      Car vehicle;



      vehicle.Mileage = 42580;

      cout << "Car Characteristics\n";

      cout << "Mileage:   " << vehicle.Mileage;



    return 0;

}

In the same way, the hidden parts are in a section that starts with the private keyword followed by a semi-colon. If you don't specify these sections, all of the members of a class are considered private.

The difference between a class and a structure is that, by default, all of the members of a class are private and, by default, all of the members of a structure are public. That is how it works if you don't create your own public and private sections. For example, the following program will not compile:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Car

{

        int      Year;

        unsigned NumberOfDoors;

        long     Mileage;

        char     DrivingCondition;

};



int main( int argc, char * argv[] )

{

      Car vehicle;



      vehicle.Mileage = 42580;

      cout << "Car Characteristics\n";

      cout << "Mileage:   " << vehicle.Mileage;



    return 0;

}

The reason is that the Mileage member variable that belongs to a class type is private and therefore cannot be accessed from main(). To resume, when creating your class, you can specify the necessary access levels using the public: and private: sections. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

public:

        int      Year;

        unsigned NumberOfDoors;

        bool     HasAirCondition;

private:

        char     DrivingCondition;

        short    TypeOfTransmission;

        char     Color;

public:

        long     Mileage;

};



int main( int argc, char * argv[] )

{

      Car vehicle;



      vehicle.Mileage = 42580;

      cout << "Car Characteristics\n";

      cout << "Mileage:   " << vehicle.Mileage;



    return 0;

}

As you can see from this class, there are no rules as to the number of public or private sections you can have in a class. There are no rules on the order of the access levels: you can create a public or a private section anywhere in the class, just remember that any member under an access level follows the rules of that access. The fact that you use different public sections does not by any means provide different public levels to the variables. A variable declared as public in one public section has the same public level of access as any other variable that is declared in another public section.

 

Object Initialization

 

Initializing Each Member of a Class

Just as variables of primitive types, an object declared from a class can also be initialized. There are various techniques you can use: initializing individual members or initializing the class as a whole.

To initialize a member of a class, access it and assign it an appropriate value using the rules of C++:

  • If the member is a numeric type, assign it a number of your choice
  • If the member is a char type, assign it a symbol or character in single-quotes
  • If the member is of type bool, assign it true or false
  • If the member is a string type, assign it a value in double-quotes
  • If the member is an array of character, use the strcpy() function to copy a value into it

Here are examples:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

    char     Make[40];

    char     Model[40];

    int      Year;

    unsigned NumberOfDoors;

    bool     HasAirCondition;

    long     Mileage;

};



int main( int argc, char * argv[] )

{

    Car vehicle;



    vehicle.Mileage = 42885;

    strcpy(vehicle.Model, "Escort");

    vehicle.NumberOfDoors = 4;

    strcpy(vehicle.Make, "Ford");

    vehicle.HasAirCondition = true;

    vehicle.Year = 2000;



    cout << "Car Auctions - Vehicle Characteristics";

    cout << "\nYear:    " << vehicle.Year;

    cout << "\nMileage: " << vehicle.Mileage;

    cout << "\nMake:    " << vehicle.Make;

    cout << "\nModel:   " << vehicle.Model;

    cout << "\nDoors:   " << vehicle.NumberOfDoors;

    cout << "\nHas A/C: " << vehicle.HasAirCondition;



    return 0;

}

This would produce:

Car Auctions - Vehicle Characteristics

Year:    2000

Mileage: 42885

Make:    Ford

Model:   Escort

Doors:   4

Has A/C: 0
 

Initializing an Object as a Whole

You can also initialize an object as a variable. This time, type the name of the variable followed by the assignment operator, followed by the desired values of the variables listed between an opening and a closing curly brackets. Here are the rules you must follow:

  • The list of values must follow the order of the declared member variables of the class
  • The values are separated with commas
  • None of the members of the class can be another class. For example, no member variable should have been declared as string

Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

    char     Make[40];

    char     Model[40];

    int      Year;

    unsigned NumberOfDoors;

    bool     HasAirCondition;

    long     Mileage;

};



int main( int argc, char * argv[] )

{

    Car SUV = { "Toyota", "4-Runner", 1998, 5, true, 57922 };





    cout << "Car Auctions - Vehicle Characteristics";

    cout << "\nYear:    " << SUV.Year;

    cout << "\nMileage: " << SUV.Mileage;

    cout << "\nMake:    " << SUV.Make;

    cout << "\nModel:   " << SUV.Model;

    cout << "\nDoors:   " << SUV.NumberOfDoors;

    cout << "\nHas A/C: " << SUV.HasAirCondition;



    return 0;

}

This would produce:

Car Auctions - Vehicle Characteristics

Year:    1998

Mileage: 57922

Make:    Toyota

Model:   4-Runner

Doors:   5

Has A/C: 1
 

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:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

    static int CarsCount;

};



int main( int argc, char * argv[] )

{

    Car vehicle;



    vehicle.Year  = 1998;

    vehicle.Mileage = 57922;

    vehicle.Make  = "Toyota";

    vehicle.Model = "4-Runner";

    vehicle.NumberOfDoors = 5;



    cout << "Car Auctions - Vehicle Characteristics";

    cout << "\nYear:    " << vehicle.Year;

    cout << "\nMileage: " << vehicle.Mileage;

    cout << "\nMake:    " << vehicle.Make;

    cout << "\nModel:   " << vehicle.Model;

    cout << "\nDoors:   " << vehicle.NumberOfDoors;



    return 0;

}

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 (vehicle) object: the compiler creates and maintains the CarsCount member, whether you use it or not, whether you declare a Car variable or not.

After creating a class that contains a static member variable, if you intend to use that member, you should (in fact must) first initialize it with the value you want it to hold. Because a static member variable doesn't belong to an object, it must be initialized at file cope, by the class itself and not one of its instances.

To initialize a static member variable, outside of the class, enter its data type, followed by the name of the class, followed by the access operator "::", followed by the name of the member variable, followed by the assignment operator, and followed by a value. Like any other member variable, you can assign any appropriate value to a static member: you decide what value you want it to have. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

    static int CarsCount;

};



int Car::CarsCount = 0;



int main( int argc, char * argv[] )

{

    Car vehicle;



    return 0;

}

After creating and initializing a static member variable, to access it outside of the class, you must qualify it with the name of the class itself and not a variable of that class. Here are two examples:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

    static int CarsCount;

    static string ApplicationTitle;

};



int Car::CarsCount = 1;

string Car::ApplicationTitle = "Four-Corner Car Auctions";



int main( int argc, char * argv[] )

{

    Car vehicle;



    vehicle.Year  = 1998;

    vehicle.Mileage = 57922;

    vehicle.Make  = "Toyota";

    vehicle.Model = "4-Runner";

    vehicle.NumberOfDoors = 5;

    

    cout << Car::ApplicationTitle;

    cout << "\n - Vehicle Characteristics -";

    cout << "\nYear:    " << vehicle.Year;

    cout << "\nMileage: " << vehicle.Mileage;

    cout << "\nMake:    " << vehicle.Make;

    cout << "\nModel:   " << vehicle.Model;

    cout << "\nDoors:   " << vehicle.NumberOfDoors;

    cout << "\nCount:   " << Car::CarsCount;



    return 0;

}

This would produce:

Four-Corner Car Auctions

 - Vehicle Characteristics -

Year:    1998

Mileage: 57922

Make:    Toyota

Model:   4-Runner

Doors:   5

Count:   1

Always remember that a static member doesn't belong to a particular object, in this case vehicle. Therefore, to access it, you use the name of the class with the "::" operator. With this rule in mind, you can assign the value of a static member to a variable of the program. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

    static int CarsCount;

    static string ApplicationTitle;

};



int Car::CarsCount = 1;

string Car::ApplicationTitle = "  Four-Corner Car Auctions";



int main( int argc, char * argv[] )

{

    Car vehicle;



    vehicle.Year  = 1998;

    vehicle.Mileage = 57922;

    vehicle.Make  = "Toyota";

    vehicle.Model = "4-Runner";

    vehicle.NumberOfDoors = 5;



    int numberOfCars = Car::CarsCount;



    cout << Car::ApplicationTitle;

    cout << "\n - Vehicle Characteristics -";

    cout << "\nYear:    " << vehicle.Year;

    cout << "\nMileage: " << vehicle.Mileage;

    cout << "\nMake:    " << vehicle.Make;

    cout << "\nModel:   " << vehicle.Model;

    cout << "\nDoors:   " << vehicle.NumberOfDoors;

    cout << "\nCount:   " << numberOfCars << endl;



    return 0;

}

You can decrement or increment it as you wish:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Car

{

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

    static int CarsCount;

    static string ApplicationTitle;

};



int Car::CarsCount = 1;

string Car::ApplicationTitle = "  Four-Corner Car Auctions";



int main( int argc, char * argv[] )

{

    Car vehicle;



    vehicle.Year  = 1998;

    vehicle.Mileage = 57922;

    vehicle.Make  = "Toyota";

    vehicle.Model = "4-Runner";

    vehicle.NumberOfDoors = 5;



    cout << Car::ApplicationTitle;

    cout << "\n - Vehicle Characteristics -";

    cout << "\nYear:    " << vehicle.Year;

    cout << "\nMileage: " << vehicle.Mileage;

    cout << "\nMake:    " << vehicle.Make;

    cout << "\nModel:   " << vehicle.Model;

    cout << "\nDoors:   " << vehicle.NumberOfDoors;

    cout << "\nCount:   " << Car::CarsCount << endl;



    Car family;



    family.Mileage = 42885;

    family.Model = "Escort";

    family.NumberOfDoors = 4;

    family.Make = "Ford";

    family.Year = 2000;

    Car::CarsCount++;



    cout << "\n - Vehicle Characteristics -";

    cout << "\nYear:    " << family.Year;

    cout << "\nMileage: " << family.Mileage;

    cout << "\nMake:    " << family.Make;

    cout << "\nModel:   " << family.Model;

    cout << "\nDoors:   " << family.NumberOfDoors;

    cout << "\nCount:   " << Car::CarsCount << endl;



    return 0;

}

This would produce:

Four-Corner Car Auctions

 - Vehicle Characteristics -

Year:    1998

Mileage: 57922

Make:    Toyota

Model:   4-Runner

Doors:   5

Count:   1



 - Vehicle Characteristics -

Year:    2000

Mileage: 42885

Make:    Ford

Model:   Escort

Doors:   4

Count:   2
 

Other Techniques of Creating an Object

 

Classic C Styles

So far, to declare a variable of a class, we did this in the main() function. C++ supports another technique. You can declare a class when creating it. To do this, type the name of the class' variable between the closing curly bracket and the semi-colon. Here is an example:

#include <iostream>

using namespace std;



struct Car

{

	int      Year;

	unsigned NumberOfDoors;

	long     Mileage;

	char     DrivingCondition;

}vehicle;



int main()

{

	vehicle.Mileage = 42580;

	vehicle.NumberOfDoors = 4;

	vehicle.DrivingCondition = 'G';

	vehicle.Year = 2000;



	cout << "Car Characteristics\n";

	cout << "Year:      " << vehicle.Year << endl;

	cout << "Condition: " << vehicle.DrivingCondition << endl;

	cout << "Mileage:   " << vehicle.Mileage << endl;

	cout << "Doors:     " << vehicle.NumberOfDoors << endl;



	return 0;

}

Just like you would declare more than one variable of a class, you can declare many class instances using this technique, separating them with commas. Here are examples:

#include <iostream>

using namespace std;



struct Car

{

	int      Year;

	unsigned NumberOfDoors;

	long     Mileage;

	char     DrivingCondition;

}Sport, SUV, Bus;



int main()

{

	SUV.Mileage = 28446;

	SUV.NumberOfDoors = 5;

	SUV.DrivingCondition = 'D';

	SUV.Year = 2002;



	Sport.Mileage = 68208;

	Sport.NumberOfDoors = 2;

	Sport.DrivingCondition = 'E';

	Sport.Year = 1998;



	cout << "First Car Characteristics\n";

	cout << "Year:      " << SUV.Year << endl;

	cout << "Condition: " << SUV.DrivingCondition << endl;

	cout << "Mileage:   " << SUV.Mileage << endl;

	cout << "Doors:     " << SUV.NumberOfDoors << endl;

	

	cout << "\nSecond Car Characteristics\n";

	cout << "Year:      " << Sport.Year << endl;

	cout << "Condition: " << Sport.DrivingCondition << endl;

	cout << "Mileage:   " << Sport.Mileage << endl;

	cout << "Doors:     " << Sport.NumberOfDoors << endl;



	return 0;

}

This would produce:

First Car Characteristics

Year:      2002

Condition: D

Mileage:   28446

Doors:     5



Second Car Characteristics

Year:      1998

Condition: E

Mileage:   68208

Doors:     2

C programmers use another technique of creating classes. It consists of using the typedef keyword, which means you would define a type but set the actual name of the class between the closing curly bracket and the semi-colon. Here is an example of using that technique:

#include <iostream>

using namespace std;



typedef struct MobileEngine

{

	int      Year;

	unsigned NumberOfDoors;

	long     Mileage;

	char     DrivingCondition;

}Car;



int main()

{

	return 0;

}

Optionally, you can type a pseudo-name for the class on the first line. Here is an example: 

#include <iostream>

using namespace std;



typedef struct _car

{

	int      Year;

	unsigned NumberOfDoors;

	long     Mileage;

	char     DrivingCondition;

} Car;



int main()

{



	return 0;

}

After creating the class, the Car name is a class, not a variable. Therefore, when you want to use the object, you must and can declare an instance of the class using either the _car or the Car name. Here are examples:

#include <iostream>

using namespace std;



typedef class _car

{

	int      Year;

	unsigned NumberOfDoors;

	long     Mileage;

	char     DrivingCondition;

} Car;



int main()

{

	_car vehicle;

	Car  mobile;



	return 0;

}
 

References

As done for variables of primitive types, you can create a reference to a class using a declared variable. The same rule applies: the object that is used as a reference must have previously been initialized. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Car

{

public:

    char     Make[40];

    char     Model[40];

    int      Year;

    unsigned NumberOfDoors;

    bool     HasAirCondition;

    long     Mileage;

};



int main( int argc, char * argv[] )

{

    Car vehicle = { "Toyota", "4-Runner", 1998, 5, true, 57922 };

    Car &SUV = vehicle;



    cout << "Car Auctions - Vehicle Characteristics";

    cout << "\nYear:    " << SUV.Year;

    cout << "\nMileage: " << SUV.Mileage;

    cout << "\nMake:    " << SUV.Make;

    cout << "\nModel:   " << SUV.Model;

    cout << "\nDoors:   " << SUV.NumberOfDoors;

    cout << "\nHas A/C: " << SUV.HasAirCondition;



    return 0;

}
 

Constant Objects

Just as you can create a constant of a built-in data type, you can also create a constant using a composite type. Always remember that the constant refers to a value that doesn't change and the constant value must be initialized with a known or already defined value. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Car

{

public:

        int      Year;

        unsigned NumberOfDoors;

        bool     HasAirCondition;

private:

        char     DrivingCondition;

        short    TypeOfTransmission;

        char     Color;

public:

        long     Mileage;

};



int main( int argc, char * argv[] )

{

    Car vehicle, sportCar;



    vehicle.Mileage = 28446;

    vehicle.NumberOfDoors = 5;

    vehicle.Year = 2002;



    cout << "Vehicle Characteristics\n";

    cout << "Year:      " << vehicle.Year << endl;

    cout << "Mileage:   " << vehicle.Mileage << endl;

    cout << "Doors:     " << vehicle.NumberOfDoors << endl;



    sportCar.Mileage = 28446;

    sportCar.Year = 2002;



    const Car mobile = vehicle;



    cout << "\nSport Car Characteristics\n";

    cout << "Year:      " << sportCar.Year << endl;

    cout << "Mileage:   " << sportCar.Mileage << endl;



    cout << "\nMobile Characteristics\n";

    cout << "Year:      " << mobile.Year << endl;

    cout << "Mileage:   " << mobile.Mileage << endl;

    cout << "Doors:     " << mobile.NumberOfDoors << endl;





    return 0;

}

This would produce:

Vehicle Characteristics

Year:      2002

Mileage:   28446

Doors:     5



Sport Car Characteristics

Year:      2002

Mileage:   28446



Mobile Characteristics

Year:      2002

Mileage:   28446

Doors:     5
 

Unions

 

Introduction

Like a structure, a union is created from combining other variables. To create a union, use the union keyword following the same syntax applied for a class, like this:

union SomeName {};

Like a structure, the members of a union are listed in its body. For example, to create a union that represents a student, you would type:

union Student

{

	char FullName[32];

	int Age;

	float AvgGrade;

};

Once the union is defined, you can declare it and use its members:

#include <iostream> 

using namespace std;



union Student

{

	int Age;

	double AvgGrade;

};



int main()

{

	Student Std;



	Std.Age = 12;

	cout << "Student Age = " << Std.Age;



	return 0;

}

This would produce:

Student Age = 12
 

Using a Union

When creating a struct or a class, each variable, treated as its own entity, occupies its assigned amount of space in memory. This is different with unions. All of the members of a union share the same memory space. After declaring a union object, instead of allocating memory for each member variable, the compiler assigns an amount of memory equal to the largest variable. Therefore, if you define a union that would represent a Student object as the above, the compiler would assign the same memory space to all members; and the compiler would find out which member needs the largest space, in this case that would be the double variable because a double variable occupies 8 Bytes. Consequently, a union can store only the value of only (excuse the repetition) one of its members at a time: you cannot simultaneously access the values of all members, at the same time (another repetition).

If you initialize all of the members of a union at the same time, the result is unreliable; since all members are using the same memory space, that space cannot accommodate all member values at the same time. The following version of our program produces such an unreliable result: 

#include <iostream> 

using namespace std;



union Student

{

	char Gender;

	int Age;

	float AvgGrade;

	double GradeSum;

};



int main()

{

	Student Std;



	Std.Gender = 'F';

	Std.Age = 14;

	Std.AvgGrade = 14.50;

	Std.GradeSum = 210;



	cout << "Characteristics of this student";

	cout << "\n\tGender = " << Std.Gender;

	cout << "\n\tAge = " << Std.Age;

	cout << "\n\tAverage = " << Std.AvgGrade;

	cout << "\n\tTotal = " << Std.GradeSum;



	return 0;

}

This would produce:

Characteristics of this student

Gender = Age = 0

Average = 0

Total = 210

As you can see, you should not substitute unions and structures. You should use a union when you can/must store any kind of variable in the same location, when variables sharing the same memory location is not an issue (or a danger). Avoid using unions in highly accessed and intensive value exchanges, such as calculations or data records. A union is usually created inside of another object.

Because all members of a union share the same memory location, a union is sometimes used to identify one value to use among many. Consider the following example:

#include <iostream>

using namespace std;



union HighSchool

{

	int        RegistrationStatus;

	double Salary;

};



int main()

{

	return 0;

}

In this case, two different, obviously unrelated variables are declared. The idea here is that only one of them would be used in the program, but which one. Imagine that you are starting a program for a high school. If the person whose information is being entered in the application is a student, then you need to specify his or her registration status, the eventual values would specify Registered, Pending, or Excluded. On the other hand, if the person whose information is being entered is a staff member such as a teacher, then the registration status is irrelevant but you may want to enter his or her salary, a piece of information that is irrelevant for a student. This example shows that, for one particular record being created, only one of these two values would be considered and the other would not apply.

=======================================================================

Member Functions

Introduction

The primary motivation of using classes in a program is to create objects as complete as possible. An object must be able to handle its own business so that the other objects of the program or of another program would only need to know which object can take care of a particular need they have.

A regular variable, as a member of an object, cannot handle assignments. This job is handled by particular functions declared as members of a class. A function as a member of a class is also called a Method. On this site, the words “method” and “function”, when associated with a class, will refer to the same thing: a member function of the class.

Declaring Member Functions

A member function, also called a method, is declared like any of the functions we have used so far: it could or could not return a value. Here are two examples:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Rectangle

{

public:

    double Length;

    double Height;



public:

    double Perimeter();

    double Area();

};



int main( int argc, char * argv[])

{

    Rectangle rect = { 48.35, 36.94 };



    cout << "Rectangle Characteristics";

    cout << "\nLength:    " << rect.Length;

    cout << "\nHeight:    " << rect.Height;



    return 0;

}

This would produce:

Rectangle Characteristics

Length:    48.35

Height:    36.94

When using methods on a class, the variables are used to hold or store values, called data, of the object, while member functions are used to perform assignments as related to the class. One way you can control the data held by variables is to hide data from the "external world". To achieve this, you should declare the member variables in a private section. After doing this, use the methods in the public section(s) to help the class interact with the other objects or functions of the program.

There are at least two techniques you can use to implement a method member.

   

Method Implementation

 

Local Implementation

To implement a method in the class where it is declared, use the same techniques we used to define regular functions. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



struct Integer

{

    int  Max;

    int  Min;

    int  Size()

    {

        int length;



        length = sizeof(int);

        return length;

    }

    bool IsPositive();

    bool IsNegative();

};



int main( int argc, char * argv[])

{

    Integer number;



    cout << "Size = " << number.Size() << " bytes";

    return 0;

}

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:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Rectangle

{

public:

    double Length;

    double Height;



public:

    double Perimeter()

    {

        double p;



        p = (Length + Height) * 2;

        return p;

    }

    double Area();

};



int main( int argc, char * argv[] )

{

    Rectangle rect = { 48.35, 36.94 };



    cout << "Rectangle Characteristics";

    cout << "\nLength:    " << rect.Length;

    cout << "\nHeight:    " << rect.Height;

    cout << "\nPerimeter: " << rect.Perimeter();



    return 0;

}

This would produce:

Rectangle Characteristics

Length:    48.35

Height:    36.94

Perimeter: 170.58
 

Global Implementation

An alternative to local implementation of a method consists of defining it outside of the object. To access a method of a class when implementing it, instead of the member access operator “.”, you will use the scope resolution operator " ::".

To implement a method outside of the class, type the return value of the method, followed by the class' name, followed by the scope resolution operator “::”, followed by the method's name, followed by the arguments, if any, between parentheses, and finally define what the function should do, in its body. Here is an example: 

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Rectangle

{

public:

    double Length;

    double Height;



public:

    double Perimeter()

    {

        double p;



        p = (Length + Height) * 2;

        return p;

    }

    double Area();

};



double Rectangle::Area()

{

    double a = Height * Length;

    return a;

}



int main( int argc, char * argv[] )

{

    Rectangle rect = { 48.35, 36.94 };



    cout << "Rectangle Characteristics";

    cout << "\nLength:    " << rect.Length;

    cout << "\nHeight:    " << rect.Height;

    cout << "\nPerimeter: " << rect.Perimeter();

    cout << "\nArea:      " << rect.Area();



    return 0;

}

This would produce:

Rectangle Characteristics

Length:    48.35

Height:    36.94

Perimeter: 170.58

Area:      1786.05
 

Inline Methods

When studying functions, we learned that an assignment could be carried where it is being called. Such a function was referred to as inline. The same process can apply to a class’ member. 

To declare a class’ method as inline, precede its name with the inline keyword when declaring the method in the class. Here are examples:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Rectangle

{

public:

    double Length;

    double Height;



public:

    double Perimeter()

    {

        double p;



        p = (Length + Height) * 2;

        return p;

    }

    inline double Area();

};



inline double Rectangle::Area()

{

    double a = Height * Length;

    return a;

}



int main( int argc, char * argv[] )

{

    Rectangle rect = { 48.35, 36.94 };



    cout << "Rectangle Characteristics";

    cout << "\nLength:    " << rect.Length;

    cout << "\nHeight:    " << rect.Height;

    cout << "\nPerimeter: " << rect.Perimeter();

    cout << "\nArea:      " << rect.Area();



    return 0;

}

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. For example, the following code will work just fine:

class Rectangle

{

public:

    double Length;

    double Height;



public:

    double Perimeter()

    {

        double p;



        p = (Length + Height) * 2;

        return p;

    }

    double Area();

};



inline double Rectangle::Area()

{

    double a = Height * Length;

    return a;

}

If you decide to implement a method locally (in the class), you have the option of implementing it as inline. You can precede it with, or omit, the inline keyword:

class Box

{

public:

	inline double CalcVolume()

	{

		return Length * Width * Height;

	}

	double CalcShoeSize()

	{

		return Length - 0.35;

	}

	void Display();



private:

	double Length;

	double Width;

	double Height;

	string Color;

};

On the other hand, if you omit the inline keyword, the C++ compiler would take care of it. Normally, any function implemented in the body of the class is considered inline.

Regardless of how the member methods of an object are implemented, any method can call another without using an access operator. This allows an object’s 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. Consider the following Show() method:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Rectangle

{

public:

    void Show()

    {

        Height = 36.94;

        Length = 48.35;



        cout << "Rectangle Characteristics";

        cout << "\nLength:    " << Length;

        cout << "\nHeight:    " << Height;

        cout << "\nPerimeter: " << Perimeter();

        cout << "\nArea:      " << Area();

    }

public:

    double Length;

    double Height;



public:

    double Perimeter()

    {

        double p;



        p = (Length + Height) * 2;

        return p;

    }

    double Area();

};



inline double Rectangle::Area()

{

    double a = Height * Length;

    return a;

}



int main( int argc, char * argv[] )

{

    Rectangle rect;



    rect.Show();

    return 0;

}
 

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:

class Car

{

public:

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

public:

    static int CarsCount;

    static string ApplicationTitle;

    static void Show();

};

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 variable 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. Based on this, the above Show() method could be implemented as follows:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Car

{

public:

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

public:

    static int CarsCount;

    static string ApplicationTitle;

    static void Show()

    {

        Car vehicle;



        vehicle.Year  = 2004;

        vehicle.Mileage = 24012;

        vehicle.Make  = "Ford";

        vehicle.Model = "Crown Victoria";

        vehicle.NumberOfDoors = 4;



        cout << "\nYear:    " << vehicle.Year;

        cout << "\nMileage: " << vehicle.Mileage;

        cout << "\nMake:    " << vehicle.Make;

        cout << "\nModel:   " << vehicle.Model;

        cout << "\nDoors:   " << vehicle.NumberOfDoors;

    }

};



int Car::CarsCount = 1;

string Car::ApplicationTitle = "  Four-Corner Car Auctions";



int main( int argc, char * argv[] )

{



    cout << Car::ApplicationTitle;

    cout << "\n - Vehicle Characteristics -";

    Car::Show();

    cout << "\nCount:   " << Car::CarsCount << endl;



    return 0;

}

This would produce:

Four-Corner Car Auctions

 - Vehicle Characteristics -

Year:    2004

Mileage: 24012

Make:    Ford

Model:   Crown Victoria

Doors:   4

Count:   1

Notice that, inside of main(), you don't need a Car object (an instance of the Car class) in order to access the Show() method. Also, as mentioned already, you cannot implicitly access the non-static regular members of the class inside of the static method. For example, the following code will not work:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Car

{

public:

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

public:

    static int CarsCount;

    static string ApplicationTitle;

    static void Show()

    {

        cout << "\nYear:    " << Year;

        cout << "\nMileage: " << Mileage;

        cout << "\nMake:    " << Make;

        cout << "\nModel:   " << Model;

        cout << "\nDoors:   " << NumberOfDoors;

    }

};



int Car::CarsCount = 1;

string Car::ApplicationTitle = "  Four-Corner Car Auctions";



int main( int argc, char * argv[] )

{



    cout << Car::ApplicationTitle;

    cout << "\n - Vehicle Characteristics -";

    Car::Show();

    cout << "\nCount:   " << Car::CarsCount << endl;



    return 0;

}

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 is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Car

{

public:

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

public:

    static int CarsCount;

    static string ApplicationTitle;

    static void Show();

};



int Car::CarsCount = 1;

string Car::ApplicationTitle = "  Four-Corner Car Auctions";



void Car::Show()

{

    Car vehicle;



    vehicle.Year  = 2004;

    vehicle.Mileage = 24012;

    vehicle.Make  = "Ford";

    vehicle.Model = "Crown Victoria";

    vehicle.NumberOfDoors = 4;



    cout << "\nYear:    " << vehicle.Year;

    cout << "\nMileage: " << vehicle.Mileage;

    cout << "\nMake:    " << vehicle.Make;

    cout << "\nModel:   " << vehicle.Model;

    cout << "\nDoors:   " << vehicle.NumberOfDoors;

}



int main( int argc, char * argv[] )

{



    cout << Car::ApplicationTitle;

    cout << "\n - Vehicle Characteristics -";

    Car::Show();

    cout << "\nCount:   " << Car::CarsCount << endl;



    return 0;

}

To access a static member from a static method, you don't have to qualify it: its name would be enough. Consider the following example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Car

{

public:

    string   Make;

    string   Model;

    int      Year;

    unsigned NumberOfDoors;

    long     Mileage;

public:

    static int CarsCount;

    static string ApplicationTitle;

    static void Show();

};



int Car::CarsCount = 1;

string Car::ApplicationTitle = "  Four-Corner Car Auctions";



void Car::Show()

{

    Car vehicle;



    vehicle.Year  = 2004;

    vehicle.Mileage = 24012;

    vehicle.Make  = "Ford";

    vehicle.Model = "Crown Victoria";

    vehicle.NumberOfDoors = 4;



    cout << ApplicationTitle;

    cout << "\n - Vehicle Characteristics -";

    cout << "\nYear:    " << vehicle.Year;

    cout << "\nMileage: " << vehicle.Mileage;

    cout << "\nMake:    " << vehicle.Make;

    cout << "\nModel:   " << vehicle.Model;

    cout << "\nDoors:   " << vehicle.NumberOfDoors;

    cout << "\nCount:   " << CarsCount << endl;

}



int main( int argc, char * argv[] )

{

    Car::Show();



    return 0;

}

Notice that the only members that are accessed in the static method without being qualified are the static member variables of the same class.

 

Methods and Arguments 

 

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:

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:

class Box

{

public:

    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:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Box

{

public:

    double FaceArea(double length, double height)

    {

        double area = length * height;

        return area;

    }

    double TopArea(double length, double width)

    {

        return length * width;

    }



    double RightArea(double height, double width)

    {

        return height * width;

    }

};



int main( int argc, char * argv[] )

{

    Box sampleBox;

    const double L = 35.85;

    const double H = 28.46;

    const double W = 22.08;



    cout << " -=- Box Areas -=-";

    cout << "\nTop:   " << sampleBox.TopArea(L, W);

    cout << "\nFace:  " << sampleBox.FaceArea(L, H);

    cout << "\nRight: " << sampleBox.RightArea(H, W);



    return 0;

}

This would produce:

-=- Box Areas -=-

Top:   791.568

Face:  1020.29

Right: 628.397
 

Constant Methods

Some of the methods of an object, though using member variables of the same object, don't modify them. Consider the following program:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Box

{

public:

    double Length;

    double Width;

    double Height;

public:

    double FaceArea()

    {

        return Length * Height;

    }

    double TopArea()

    {

        return Length * Width;

    }



    double RightArea()

    {

        return Height * Width;

    }

};



int main( int argc, char * argv[] )

{

    Box sampleBox;

    sampleBox.Length = 35.85;

    sampleBox.Height = 28.46;

    sampleBox.Width = 22.08;



    cout << " -=- Box Characteristics -=-";

    cout << "\nLength:       " << sampleBox.Length;

    cout << "\nWidth:        " << sampleBox.Width;

    cout << "\nHeight:       " << sampleBox.Height;

    cout << "\nTop Area:   " << sampleBox.TopArea();

    cout << "\nFace Area:  " << sampleBox.FaceArea();

    cout << "\nRight Area: " << sampleBox.RightArea();



    return 0;

}

Notice that the methods that calculate the areas don't modify the values of the member variables they are using. If a method doesn't modify the member variables of its class, the method should be declared and implemented as constant.

To declare a method as a constant, add the const keyword to the right side of the method when declaring and when implementing it. Here are examples:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Box

{

public:

    double Length;

    double Width;

    double Height;

public:

    double FaceArea() const;

    double TopArea() const

    {

        return Length * Width;

    }



    double RightArea() const

    {

        return Height * Width;

    }

};



double Box::FaceArea() const

{

    return Length * Height;

}



int main( int argc, char * argv[] )

{

    Box sampleBox;

    sampleBox.Length = 35.85;

    sampleBox.Height = 28.46;

    sampleBox.Width = 22.08;



    cout << " -=- Box Characteristics -=-";

    cout << "\nLength:     " << sampleBox.Length;

    cout << "\nWidth:      " << sampleBox.Width;

    cout << "\nHeight:     " << sampleBox.Height;

    cout << "\nTop Area:   " << sampleBox.TopArea();

    cout << "\nFace Area:  " << sampleBox.FaceArea();

    cout << "\nRight Area: " << sampleBox.RightArea();



    return 0;

}

If you decide to define constant methods locally (inline), the only difference is to remove the semi-colon of the end of the declaration and define the method normally.

You can also reinforce the constancy of the methods by starting them with the const keyword. The program would still produce the same result.

 

Private Methods

At this time, we know that one of the responsibilities of a member method of an object is to carry assignments. Another job performed by methods is to communicate with the clients of an object. As you might have found out, some of the methods of an object 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 methods, 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 the private section of the object. To implement it, follow the same rules we have learned about implementing the methods of an object. The biggest difference you must keep in mind (which will also be very important when we learn about inheritance) is that this function method is not available to the outside world. Here is an example:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

using namespace std;



class Box

{

public:

    double Length;

    double Width;

    double Height;

private:

    const double FaceArea() const;

    const double TopArea() const

    {

        return Length * Width;

    }



    const double RightArea() const

    {

        return Height * Width;

    }



public:

    void Show()

    {

        cout << "\nLength:     " << Length;

        cout << "\nWidth:      " << Width;

        cout << "\nHeight:     " << Height;

        cout << "\nTop Area:   " << TopArea();

        cout << "\nFace Area:  " << FaceArea();

        cout << "\nRight Area: " << RightArea();

    }

};



const double Box::FaceArea() const

{

    return Length * Height;

}



int main( int argc, char * argv[] )

{

    Box sampleBox;

    sampleBox.Length = 35.85;

    sampleBox.Height = 28.46;

    sampleBox.Width = 22.08;



    cout << " -=- Box Characteristics -=-";

    sampleBox.Show();



    return 0;

}
 

C++ Project Files and Classes 

 

Introduction

An object is made of the material that composes it and the actual structure of the object, which defines how the object is built and used. This means that a class is made of two parts: its building block and its definition. These two parts of a class can be kept in different files that have access to each other.

Class' Header File

The building block or foundation of an class is made of the class' creation, listing all of its members. This foundation can be created in a file called a header file, similar to the one we learned when studying functions. The name of the file follows the naming rules we have applied so far. The header file has an extension of .h.

You create an object’s header file the same we did when studying functions. To create the header file, you can just define the class as an object. If some of the members are defined in files outsde of the object, include their header file(s).

Here is what our Box header file would look like:

//---------------------------------------------------------------------------

// Box.h

//---------------------------------------------------------------------------

#if !defined(Box_H)

#define Box_H



class Box

{

public:

    double Length;

    double Width;

    double Height;

private:

    const double FaceArea() const;

    const double TopArea() const;

    const double RightArea() const;



public:

    void Show();

};



#endif // Box_H
 

Class Source Code

The file used to implement the class is called a source file. It can be used to define the assignments of the class. A source file should at least start with a line that specifies the name of the header file that it is implementing. Since this file is usually created in the same project, it is specified with an include line that encloses the file name with double-quotes. An example would be:

#include "Book.h"

The main area of the file is made of the class' implementation. Here is what the source file of our Box would look like:

//---------------------------------------------------------------------------

// Unit1.cpp

//---------------------------------------------------------------------------



#include <iostream>

#include "box.h"



using namespace std;



const double Box::FaceArea() const

{

    return Length * Height;

}



const double Box::TopArea() const

{

    return Length * Width;

}



const double Box::RightArea() const

{

    return Height * Width;

}



void Box::Show()

{

    cout << "\nLength:     " << Length;

    cout << "\nWidth:      " << Width;

    cout << "\nHeight:     " << Height;

    cout << "\nTop Area:   " << TopArea();

    cout << "\nFace Area:  " << FaceArea();

    cout << "\nRight Area: " << RightArea();

}

The main() function of our box project is reduced to simply calling the appropriate Box method member:

#ifdef __BORLANDC__

  #pragma argsused

#endif



#include <iostream>

#include "box.h"



using namespace std;



int main( int argc, char * argv[] )

{

    Box sampleBox;

    sampleBox.Length = 35.85;

    sampleBox.Height = 28.46;

    sampleBox.Width = 22.08;



    cout << " -=- Box Characteristics -=-";

    sampleBox.Show();



    return 0;

}
========================================================================

Constructors

Method Initializer

In order to further customize the behavior of an object, you should make sure that it completely controls its member variables. An object should "know" what kind of values its variables hold and what values are not acceptable. As a starting point, when calling an object from another function, you should know what value a particular member is holding, before performing any operation. To solve this problem, one solution is to provide a special function that would initialize the member variables.

A method that initializes can return any value but it is preferable to return a 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 would initialize.

Consider an object used to handle a brick; a rectangular parallelepiped is recognized by its length, height, and width. A method used to initialize its dimensions would look like this:

//---------------------------------------------------------------------------

#include <iostream> 

using namespace std;

struct TBrick

{

public:

    void Initializer(double l, double h, double w);

    double Volume() const;

    void Properties() const;

private:

    double Length;

    double Height;

    double Width;

};

//---------------------------------------------------------------------------

void TBrick::Initializer(double l, double h, double w)

{

    Length = l;

    Height = h;

    Width = w;

}

//---------------------------------------------------------------------------

double TBrick::Volume() const

{

    return Length * Height * Width;

}

//---------------------------------------------------------------------------

void  TBrick::Properties() const

{

    cout << "Red Brick Properties";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nLength = " << Length;

    cout << "\nHeight = " << Height;

    cout << "\nThickness = " << Width;

    cout << "\nVolume = " << Volume() << "\n";

}

//---------------------------------------------------------------------------

int main()

{

    TBrick RedBrick;



    RedBrick.Initializer(124.45, 56.25, 32.55);

    RedBrick.Properties();

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce:

Red Brick Properties

Length = 124.45

Height = 56.25

Thickness = 32.55

Volume = 227860.17



Press any key to continue...

Once declared and implemented, a method initializer can be used as the "entry point" to the object; for example, it can be used to pass values from the external world to the member variables of an object. In the following example, the user supplies the dimensions of the brick. Since the dimensions are held by private members, their values will be carried from the outside by the method used to initialize:

//---------------------------------------------------------------------------

int main()

{

    double length, height, width;

    TBrick GoneSand;



    cout << "Before building this brick, provide its dimensions\n";

    cout << "Length: ";

    cin >> length;

    cout << "Height: ";

    cin >> height;

    cout << "Width:  ";

    cin >> width;

    cout << endl;



    GoneSand.Initializer(length, height, width);

    GoneSand.Properties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

An example of running the program would produce: 

Before building this brick, provide its dimensions

Length: 8.95

Height: 6.85

Width:  6.25



Red Brick Properties

Length    = 8.95

Height    = 6.85

Thickness = 6.25

Volume    = 383.17



Press any key to continue...
  

Initializing an Object

  1. To create a new project, on the main menu, click File -> New or File -> New -> Other...
  2. On the New Items dialog box, double-click Console Wizard.
  3. On the Console Wizard dialog box, make sure the C++ radio button is selected. In the right section, click only the Console Application check box and click OK.
  4. To save the project, on the Standard toolbar, click the Save All button.
  5. Click the Create New Folder button, type Students2 and press Enter twice to put the new folder name in the Save In combo box.
  6. Change the File Name content to Main and press Enter.
  7. For the name of the project, type Student and press Enter.
  8. To add a new unit, on the main menu, click File -> New or File -> New -> Other...
  9. In the New Items dialog box, double-click Unit.
  10. To save the unit, on the Standard toolbar, click the Save button.
  11. Type Students as the unit name and press Enter.
  12. Click the Students.h tab and change its content as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <string>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
        void  InitialValues(string fn, string ln,
    
                                     int DOB, int MOB, int YOB);
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  13. Click the Students.cpp file and change it as follows:
     

    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    void  TStudent::InitialValues(string fn, string ln,
    
                                     int DOB, int MOB, int YOB)
    
    {
    
        FirstName    = fn;
    
        LastName     = ln;
    
        DayOfBirth   = DOB;
    
        MonthOfBirth = MOB;
    
        YearOfBirth  = YOB;
    
    }
    
    //---------------------------------------------------------------------------
    
    void  TStudent::Display()
    
    {
    
        // Display the characteristics of the student
    
        cout << "Characteristics of this student";
    
        cout << "\nFull Name: " << FirstName << " " << LastName;
    
        cout << "\nDate of Birth: " << DayOfBirth
    
             << "/" << MonthOfBirth << "/" << YearOfBirth << "\n";
    
    }
    
    //---------------------------------------------------------------------------
  14. Click the Main.cpp file and change it as follows:
     

    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    void  Exit()
    
    {
    
        cout << "\n\nPress any key to continue...";
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    int main()
    
    {
    
        TStudent FirstGrade;
    
    
    
        FirstGrade.InitialValues("Jules", "Senga", 1, 1, 1990);
    
        FirstGrade.Display();
    
    
    
        Exit();
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  15. Press F9 to test the program.

Default Constructor

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

When you create an object, if you do not declare a constructor, the compiler would create one for your program; 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 declare your own constructor, simply add a method with the same name as the object in the public section of the object. 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.

A constructor is declared without a return value, that also excludes void. Therefore, when implemented, do not return a value:

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

//---------------------------------------------------------------------------



struct TBook

{

public:

    TBook();    // Constructor

};

//---------------------------------------------------------------------------

TBook::TBook()

{

    cout << "I see a book...\n";

}

//---------------------------------------------------------------------------

int main()

{

    TBook B;



    return 0;

}

//---------------------------------------------------------------------------

This would produce:

I see a book...

This book constructor is a programmer created constructor and is empty. 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. A constructor is easily implemented once you have created one:

There are various categories of bricks used in the construction industry.

For this exercise, we will consider a simple one used in constructing domestic building foundations. It has a total length, here called Length; it also has a height, referred here to as Height; and it has a thickness that will be called Thickness. For resistance and static reasons, our brick will have two holes. Since we are more interested in the amount of cement used to create the brick, we will subtract the volume of the hole from the total volume. The dimensions we use are for simplicity. We will consider that the small wall of the brick has a thickness of 0.25; also, the static wall in the middle length has a thickness of 0.25.

Listing - Brick Unit - Header File: Bricks.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

struct TBrick

{

public:

     TBrick(); // Empty Constructor

    void  setDimensions(double l, double h, double t);

    void  Initializer(double l, double h, double w);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

Brick Unit - Source File: Bricks.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;



#include "Bricks.h"



//---------------------------------------------------------------------------





//---------------------------------------------------------------------------

 TBrick::TBrick()

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

void  TBrick::setDimensions(double l, double h, double t)

{

    Length = l;

    Height = h;

    Thickness = t;

}

//---------------------------------------------------------------------------

double  TBrick::CementVolume()

{

    double Enclosure = 0.50; // This includes both walls of the brick itself

    double HoleLength = Length - 0.75; // Including both holes

    double HoleThickness = Thickness - Enclosure;

    double HoleVolume = HoleLength * HoleThickness * Height;

    double TotalVolume = Length * Height * Thickness;

    double ValidVolume = TotalVolume - HoleVolume;



    return ValidVolume;

}

//---------------------------------------------------------------------------

void  TBrick::ShowProperties()

{

    cout << "Foundation Brick Properties";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nLength    = " << Length; cout

         << "\nHeight    = " << Height;

    cout << "\nThickness = " << Thickness;

    cout << "\nCement Volume = " << CementVolume() << "\n";

}//---------------------------------------------------------------------------

Main File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

int main()

{

    TBrick Foundation;



    Foundation.setDimensions(4.24, 3.55, 3.45);

    Foundation.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This program would produce:

Foundation Brick Properties

Length    = 4.24

Height    = 3.55

Thickness = 3.45

Cement Volume = 15.38



Press any key to continue...
 

Using the Default Constructor

  1. Access the Students.h file and change it as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <string> 
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent();
    
        void  InitialValues(string fn, string ln,
    
                                     int DOB, int MOB, int YOB);
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  2. Change the Students.cpp file accordingly:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    //---------------------------------------------------------------------------
    
     TStudent::STudent()
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    void  TStudent::InitialValues(string fn, string ln,
    
                                     int DOB, int MOB, int YOB)
    
    {
    
        FirstName    = fn;
    
        LastName     = ln;
    
        DayOfBirth   = DOB;
    
        MonthOfBirth = MOB;
    
        YearOfBirth  = YOB;
    
    }
    
    //---------------------------------------------------------------------------
    
    void  TStudent::Display()
    
    {
    
        // Display the characteristics of the student
    
        cout << "Characteristics of this student";
    
        cout << "\nFull Name: " << FirstName << " " << LastName;
    
        cout << "\nDate of Birth: " << DayOfBirth
    
             << "/" << MonthOfBirth << "/" << YearOfBirth << "\n";
    
    }
    
    //---------------------------------------------------------------------------
  3. Press F9 to test the program.

The Constructor Initializer

A constructor does not exist simply for cosmetic reasons. It can be used to initialize the member variables of an object. Therefore, 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 do not 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 do not need to modify (or access) or the member variable will be initialized later when called from the needed object or function. To initialize the members of our Brick object, its method constructor would be declared as in the following file:

Listing - Brick Unit - Header File: Bricks.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

struct TBrick

{

public:

     TBrick();    // Default Constructor

     TBrick(double l, double h, double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

Listing - Brick Unit - Source File: Bricks.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;



#include "Bricks.h"



//---------------------------------------------------------------------------





//---------------------------------------------------------------------------

 TBrick::TBrick()

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

 TBrick::TBrick(double l, double h, double t)

{

    Length = l;

    Height = h;

    Thickness = t;

}

//---------------------------------------------------------------------------

double  TBrick::CementVolume()

{

    double Enclosure = 0.50; // This includes both walls of the brick itself

    double HoleLength = Length - 0.75; // Including both holes

    double HoleThickness = Thickness - Enclosure;

    double HoleVolume = HoleLength * HoleThickness * Height;

    double TotalVolume = Length * Height * Thickness;

    double ValidVolume = TotalVolume - HoleVolume;



    return ValidVolume;

}

//---------------------------------------------------------------------------

void  TBrick::ShowProperties()

{

    cout << "Foundation Brick Properties";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nLength    = " << Length; cout

         << "\nHeight    = " << Height;

    cout << "\nThickness = " << Thickness;

    cout << "\nCement Volume = " << CementVolume() << "\n";

}

//---------------------------------------------------------------------------

Main File: Main.cpp

//---------------------------------------------------------------------------



#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

int main()

{

    TBrick Solid(4.15, 3.35, 3.05);

    Solid.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce the following result:

Foundation Brick Properties

Length    = 4.15

Height    = 3.35

Thickness = 3.05

Cement Volume = 13.36



Press any key to continue...

To safeguard and protect the member variables of an object, we have learned to use set and get methods. If you use set methods to protect the variables of an object, you can conveniently call these methods from the constructor to initialize those member variables. Therefore, a constructor can also be used to call methods that hold the initial values of member variables.

At this time, we have learned that a constructor is mainly used to set the initial values of necessary member variables. When using set methods, our Brick object would be changed as follows:

Brick Unit - Header File: Bricks.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

struct TBrick

{

public:

     TBrick();    // Default Constructor

     TBrick(double l, double h, double t);

    void  setLength(double l);

    void  setHeight(double h);

    void  setThickness(double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

Brick Unit - Source File: Brick.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;



#include "Bricks.h"



//---------------------------------------------------------------------------





//---------------------------------------------------------------------------

 TBrick::TBrick()

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

 TBrick::TBrick(double l, double h, double t)

{

    setLength(l);

    setHeight(h);

    setThickness(t);

}

//---------------------------------------------------------------------------

void  TBrick::setLength(double l)

{

    Length = l;

}

//---------------------------------------------------------------------------

void  TBrick::setHeight(double h)

{

   Height = h;

}

//---------------------------------------------------------------------------

void  TBrick::setThickness(double t)

{

    Thickness = t;

}

//---------------------------------------------------------------------------

double  TBrick::CementVolume()

{

    double Enclosure = 0.50; // This includes both walls of the brick itself

    double HoleLength = Length - 0.75; // Including both holes

    double HoleThickness = Thickness - Enclosure;

    double HoleVolume = HoleLength * HoleThickness * Height;

    double TotalVolume = Length * Height * Thickness;

    double ValidVolume = TotalVolume - HoleVolume;



    return ValidVolume;

}

//---------------------------------------------------------------------------

void  TBrick::ShowProperties()

{

    cout << "Foundation Brick Properties";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nLength    = " << Length; cout

         << "\nHeight    = " << Height;

    cout << "\nThickness = " << Thickness;

    cout << "\nCement Volume = " << CementVolume() << "\n";

}

//---------------------------------------------------------------------------

Main File: Main.cpp

//---------------------------------------------------------------------------



#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

int main()

{

    TBrick Solid(4.15, 3.35, 3.05);

    Solid.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce:

Foundation Brick Properties

Length    = 4.15

Height    = 3.35

Thickness = 3.05

Cement Volume = 13.36



Press any key to continue...
 

Initializing With the Constructor

  1. Add a constructor to the Students object as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB);
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  2. Change the Students.cpp file: 
     
    //---------------------------------------------------------------------------
    
    
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(string fn, string ln,
    
                                  int DOB, int MOB, int YOB)
    
    {
    
        FirstName    = fn;
    
        LastName     = ln;
    
        DayOfBirth   = DOB;
    
        MonthOfBirth = MOB;
    
        YearOfBirth  = YOB;
    
    }
    
    //---------------------------------------------------------------------------
    
    void  TStudent::Display()
    
    {
    
        // Display the characteristics of the student
    
        cout << "Characteristics of this student";
    
        cout << "\nFull Name: " << FirstName << " " << LastName;
    
        cout << "\nDate of Birth: " << DayOfBirth
    
             << "/" << MonthOfBirth << "/" << YearOfBirth << "\n";
    
    }
    
    //---------------------------------------------------------------------------
  3. Finally, change the main():
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    void  Exit()
    
    {
    
        cout << "\n\nPress any key to continue...";
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    int main()
    
    {
    
        TStudent SecondGrade("Paul", "Waller", 12, 10, 1988);
    
        SecondGrade.Display();
    
    
    
        Exit();
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  4. Press F9 to test the program:

    Characteristics of this student Full Name: John Doe Date of Birth: 1/1/1990Press any key to continue...
  5. Return to your programming environment.

Constructor Overloading

Like an ordinary method, a construction can be overloaded. This means that you can have different constructors following the rules of overloading a function. Since we saw that a constructor can be used to initialize the member variables of its object, you can use multiple constructors to apply different initializations.

If you declare a constructor as

TBrick Foundation;

you can use it to call other method members of the same object. The problem is that if you just try to call a method that displays the values of the member variables, you will get bizarre and unpredictable results. Consider the TBrick object created as

//---------------------------------------------------------------------------

struct TBrick

{

public:

     TBrick();

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

And implemented as

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;



#include "Bricks.h"

//---------------------------------------------------------------------------



 TBrick::TBrick()

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

double  TBrick::CementVolume()

{

    double Enclosure = 0.50; // This includes both walls of the brick itself

    double HoleLength = Length - 0.75; // Including both holes double

    double HoleThickness = Thickness - Enclosure;

    double HoleVolume = HoleLength * HoleThickness * Height;

    double TotalVolume = Length * Height * Thickness;

    double ValidVolume = TotalVolume - HoleVolume;



    return ValidVolume;

}

//---------------------------------------------------------------------------

void  TBrick::ShowProperties()

{

    cout << "Foundation Brick Properties";

    cout << "\nLength = " << Length;

    cout << "\nHeight = " << Height;

    cout << "\nThickness = " << Thickness;

    cout << "\nCement Volume = " << CementVolume() << "\n";

}

//---------------------------------------------------------------------------

If you declare the TBrick object using the default constructor, and decide to call a method that displays the variables values, you could write it like this:

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    TBrick Mango;



    Mango.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce the following result:

Foundation Brick Properties

Length = nan

Height = 2.53988e-314

Thickness = 2.122e-314

Cement Volume = nan



Press any key to continue...

As you can see, these values do not make sense to us.

To make sure that a calling function does not have to supply values for the member variables, you can also use the empty constructor to supply default values to these variables. If you simply use the default constructor to get the values of the member variables, the object would use the values given in the empty constructor and perform all necessary operations:

 TBrick::TBrick()

{

    Length = 4.15;

    Height = 3.55;

    Thickness = 3.75;

}

This time, the same program would produce a sound result:

Foundation Brick Properties

Length = 4.15

Height = 3.55

Thickness = 3.75

Cement Volume = 16.0194



Press any key to continue...

This technique of using the default constructor allows you to conveniently supply default values for the member variables. As flexible as this is, you can use a certain constructor to initialize just one of the member variables and supply default values for the others. When constructing a brick, one of the dimensions would be of primary importance because it influences what the brick is used for. On this exercise, let's allow a calling function to supply the length of the brick while we control the other two dimensions. We can declare more than one constructor in the header file:

Brick Unit - Header File: Brick.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick();

     TBrick(double L);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

Brick Unit - Source File: Brick.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;



#include "Bricks.h"

//---------------------------------------------------------------------------



 TBrick::TBrick()

{

    Length = 4.15;

    Height = 3.55;

    Thickness = 3.75;

}

//---------------------------------------------------------------------------

 TBrick::TBrick(double L)

{

    Length = L;

    Height = 5.25;

    Thickness = 4.55;

}

//---------------------------------------------------------------------------

double  TBrick::CementVolume()

{

    ...

}

//---------------------------------------------------------------------------

void  TBrick::ShowProperties()

{

    ...

}

//---------------------------------------------------------------------------

Since this constructor takes one argument, when declaring an object that would use this constructor, assign only one value to the argument variable. Such a value is provided in the parentheses allocated to the instance of the object. Here is an example:

Main File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    // Brick with default dimensions

    TBrick Mather;

    Mather.ShowProperties();

    cout << endl;



    // Brick with a supplied length

    TBrick BedTimer(5.55);

    BedTimer.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce the following result:

Foundation Brick Properties

Length = 4.15

Height = 3.55

Thickness = 3.75

Cement Volume = 16.0194



Foundation Brick Properties

Length = 5.55

Height = 5.25

Thickness = 4.55

Cement Volume = 30.5156



Press any key to continue...

If you declare 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 would complain.

Here is our program that makes use of three constructors, each with different arguments:

Brick Unit - Header File: Brick.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick();

     TBrick(double L);

     TBrick(double L, double h, double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

The new constructor can be implemented as follows:

//---------------------------------------------------------------------------

 TBrick::TBrick(double L, double h, double t)

{

    Length = L;

    Height = h;

    Thickness = t;

}//---------------------------------------------------------------------------

Main File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    // Brick with default dimensions

    TBrick GrayMatte;

    GrayMatte.ShowProperties();

    cout << endl;



    // Brick with a supplied length

    TBrick OldTimer(5.55);

    OldTimer.ShowProperties();

    cout << endl;



    // A Brick with set dimensions

    TBrick Fantasma(3.25, 3.05, 3.25);

    Fantasma.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce:

Foundation Brick Properties

Length = 4.15

Height = 3.55

Thickness = 3.75

Cement Volume = 16.0194



Foundation Brick Properties

Length = 5.55

Height = 5.25

Thickness = 4.55

Cement Volume = 30.5156



Foundation Brick Properties

Length = 3.25

Height = 3.05

Thickness = 3.25

Cement Volume = 11.2469



Press any key to continue...

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. For example if you create a TBrick object as follows:

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick(double L, double h, double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

and implement the TBrick(double L, double h, double t) constructor as we saw above, the following main() function would halt the program:

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    // The following (default) constructor is not available

    TBrick GrayMatte;

    GrayMatte.ShowProperties();

    cout << endl;



    // A Brick with set dimensions

    TBrick Fantasma(3.25, 3.05, 3.25);

    Fantasma.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

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

Based on what we have learned already, here is our complete program with set and get methods. 

Brick Unit - Header File: Brick.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick();

     TBrick(double L);

     TBrick(double L, double h, double t);

    double  getLength() const;

    void  setLength(const double l);

    double  getHeight() const;

    void  setHeight(const double h);

    double  getThickness() const;

    void  setThickness(const double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

Brick Unit - Source File: Brick.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;



#include "Bricks.h"

//---------------------------------------------------------------------------



 TBrick::TBrick()

{

    Length = 4.15;

    Height = 3.55;

    Thickness = 3.75;

}

//---------------------------------------------------------------------------

 TBrick::TBrick(double L)

{

    Length = L;

    Height = 5.25;

    Thickness = 4.55;

}

//---------------------------------------------------------------------------

 TBrick::TBrick(double L, double h, double t)

{

    Length = L;

    Height = h;

    Thickness = t;

}

//---------------------------------------------------------------------------

double  TBrick::getLength() const

{

    return Length;

}

//---------------------------------------------------------------------------

void  TBrick::setLength(const double l)

{

    Length = l;

}

//---------------------------------------------------------------------------

double  TBrick::getHeight() const

{

    return Height;

}

//---------------------------------------------------------------------------

void  TBrick::setHeight(const double h)

{

    Height = h;

}

//---------------------------------------------------------------------------

double  TBrick::getThickness() const

{

    return Thickness;

}

//---------------------------------------------------------------------------

void  TBrick::setThickness(const double t)

{

    Thickness = t;

}

//---------------------------------------------------------------------------

double  TBrick::CementVolume()

{

    double Enclosure = 0.50; // This includes both walls of the brick itself

    double HoleLength = Length - 0.75; // Including both holes double

    double HoleThickness = Thickness - Enclosure;

    double HoleVolume = HoleLength * HoleThickness * Height;

    double TotalVolume = Length * Height * Thickness;

    double ValidVolume = TotalVolume - HoleVolume;



    return ValidVolume;

}

//---------------------------------------------------------------------------

void  TBrick::ShowProperties()

{

    cout << "Foundation Brick Properties";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nLength = " << Length;

    cout << "\nHeight = " << Height;

    cout << "\nThickness = " << Thickness;

    cout << "\nCement Volume = " << CementVolume() << "\n";

}

//---------------------------------------------------------------------------

Main File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    // Brick with default dimensions

    TBrick GrayMatte;

    GrayMatte.ShowProperties();

    cout << endl;



    // Brick with a supplied length

    TBrick OldTimer(5.55);

    OldTimer.ShowProperties();

    cout << endl;



    // A Brick with user supplied dimensions

    double len, hgt, thk;

    cout << "\nEnter the dimensions of the brick\n";

    cout << "Length: ";

    cin >> len;

    cout << "Height: ";

    cin >> hgt;

    cout << "Thickness: ";

    cin >> thk;

    cout << endl;

    TBrick Fantasma(len, hgt, thk);

    Fantasma.ShowProperties();



    

    

    

    return 0;

}

//---------------------------------------------------------------------------

Here is an example of running the program: 

Foundation Brick Properties

Length = 4.15

Height = 3.55

Thickness = 3.75

Cement Volume = 16.02



Foundation Brick Properties

Length = 5.55

Height = 5.25

Thickness = 4.55

Cement Volume = 30.52





Enter the dimensions of the brick

Length: 6.25

Height: 5.85

Thickness: 4.55



Foundation Brick Properties

Length = 6.25

Height = 5.85

Thickness = 4.55

Cement Volume = 36.05



Press any key to continue...
 

Overloading the Constructor

  1. To use an empty constructor that initializes the member variables, change the Students.h file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent();
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB);
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  2. Implement the new constructor in the Student.cpp file as follows:

    //---------------------------------------------------------------------------
    
    _fastcall TStudent::TStudent()
    
    {
    
        FirstName    = "Paul";
    
        LastName     = "Kamus";
    
        DayOfBirth   = 28;
    
        MonthOfBirth = 5;
    
        YearOfBirth  = 1986;
    
    }
    
    //---------------------------------------------------------------------------
  3. To test both constructors, change the main() function as follows:

    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    void  Exit()
    
    {
    
        cout << "\n\nPress any key to continue...";
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    int main()
    
    {
    
        TStudent SampleStudent;
    
        SampleStudent.Display();
    
        cout << endl;
    
    
    
        TStudent Complete("Alexander", "Biyidi", 30, 4, 1988);
    
        Complete.Display();
    
    
    
        Exit();
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  4. To test the program, press F9:
     

    Characteristics of this student
    
    Full Name: Paul Kamus
    
    Date of Birth: 28/5/1986
    
    
    
    Characteristics of this student
    
    Full Name: Alexander Biyidi
    
    Date of Birth: 30/4/1988
    
    
    
    
    
    Press any key to continue...
  5. Return to your programming environment.
  6. Now, we will use two more constructors. One of the constructors will initialize only the name of the student. Another constructor will set default values for the date of birth. Both constructors use the same technique but accomplish different purposes. Therefore, change the TStudent class as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent();  // Default Constructor
    
         TStudent(string F, string L); // Name Initializer
    
         TStudent(int DOB, int MOB, int YOB); // Initial Date of birth
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB); // Complete Constructor
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  7. Implement the constructors in the Students.cpp file as follows:

    //---------------------------------------------------------------------------
    
    
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    //---------------------------------------------------------------------------
    
    _fastcall TStudent::TStudent()
    
    {
    
        FirstName    = "John";
    
        LastName     = "Doe";
    
        DayOfBirth   = 1;
    
        MonthOfBirth = 1;
    
        YearOfBirth  = 1990;
    
    }
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(string FN, string LN)
    
    {
    
        FirstName    = FN;
    
        LastName     = LN;
    
        DayOfBirth   = 1;
    
        MonthOfBirth = 1;
    
        YearOfBirth  = 1985;
    
    }
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(int DOB, int MOB, int YOB)
    
    {                  
    
        FirstName    = "William";
    
        LastName     = "Smith";
    
        DayOfBirth   = DOB;
    
        MonthOfBirth = MOB;
    
        YearOfBirth  = YOB;
    
    }
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(string fn, string ln,
    
                                  int DOB, int MOB, int YOB)
    
    {
    
        FirstName    = fn;
    
        LastName     = ln;
    
        DayOfBirth   = DOB;
    
        MonthOfBirth = MOB;
    
        YearOfBirth  = YOB;
    
    }
    
    //---------------------------------------------------------------------------
    
    void  TStudent::Display()
    
    {
    
        // Display the characteristics of the student
    
        cout << "Characteristics of this student";
    
        cout << "\nFull Name: " << FirstName << " " << LastName;
    
        cout << "\nDate of Birth: " << DayOfBirth
    
             << "/" << MonthOfBirth << "/" << YearOfBirth << "\n";
    
    }
    
    //---------------------------------------------------------------------------
  8. Test the constructors in the main() function with the following:

    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    void  Exit()
    
    {
    
        cout << "\n\nPress any key to continue...";
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    int main()
    
    {
    
        TStudent DefaultStudent;
    
        DefaultStudent.Display();
    
        cout << endl;
    
    
    
        TStudent WithNameOnly("Genevieve", "Souchon");
    
        WithNameOnly.Display();
    
        cout << endl;
    
    
    
        TStudent ByDateOfBirth(12, 5, 1987);
    
        ByDateOfBirth.Display();
    
        cout << endl;
    
    
    
        TStudent Typical("William", "Tobolowski", 5, 15, 1985);
    
        Typical.Display();
    
    
    
        Exit();
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  9. Press F9 to test the program:
     

    Characteristics of this student
    
    Full Name: John Doe
    
    Date of Birth: 1/1/1990
    
    
    
    Characteristics of this student
    
    Full Name: Genevieve Souchon
    
    Date of Birth: 1/1/1985
    
    
    
    Characteristics of this student
    
    Full Name: William Smith
    
    Date of Birth: 12/5/1987
    
    
    
    Characteristics of this student
    
    Full Name: William Tobolowski
    
    Date of Birth: 5/15/1985
    
    
    
    
    
    Press any key to continue...
  10. Return to your programming environment

 

Techniques of Initializing With a Constructor

We have already seen various techniques of initializing member variables and implementing member methods. In the same way, a constructor can be defined locally, in the header file:

Brick Unit - Header File: Brick.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick(double L, double h, double t) { Length = L; Height = h; Thickness = t; }

    double  getLength() const;

    void  setLength(const double l);

    double  getHeight() const;

    void  setHeight(const double h);

    double  getThickness() const;

    void  setThickness(const double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

There is 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.

To initialize the members of our TBrick object, we can type:

Brick Unit - Header File: Brick.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick() : Length(3.25), Height(2.55), Thickness(3.55) {}

     TBrick(double L, double h, double t) { Length = L; Height = h; Thickness = t; }

    double  getLength() const;

    void  setLength(const double l);

    double  getHeight() const;

    void  setHeight(const double h);

    double  getThickness() const;

    void  setThickness(const double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

The source file would be as follows. 

Brick Unit - Source File: Brick.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;



#include "Bricks.h"

//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

double  TBrick::getLength() const

{

    return Length;

}

//---------------------------------------------------------------------------

void  TBrick::setLength(const double l)

{

    Length = l;

}

//---------------------------------------------------------------------------

double  TBrick::getHeight() const

{

    return Height;

}

//---------------------------------------------------------------------------

void  TBrick::setHeight(const double h)

{

    Height = h;

}

//---------------------------------------------------------------------------

double  TBrick::getThickness() const

{

    return Thickness;

}

//---------------------------------------------------------------------------

void  TBrick::setThickness(const double t)

{

    Thickness = t;

}

//---------------------------------------------------------------------------

double  TBrick::CementVolume()

{

    double Enclosure = 0.50; // This includes both walls of the brick itself

    double HoleLength = Length - 0.75; // Including both holes double

    double HoleThickness = Thickness - Enclosure;

    double HoleVolume = HoleLength * HoleThickness * Height;

    double TotalVolume = Length * Height * Thickness;

    double ValidVolume = TotalVolume - HoleVolume;



    return ValidVolume;

}

//---------------------------------------------------------------------------

void  TBrick::ShowProperties()

{

    cout << "Foundation Brick Properties";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nLength = " << Length;

    cout << "\nHeight = " << Height;

    cout << "\nThickness = " << Thickness;

    cout << "\nCement Volume = " << CementVolume() << "\n";

}

//---------------------------------------------------------------------------

To test the program, we would implement the main() function as follows. 

Main Unit - Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    TBrick Lott;

    Lott.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

We can use the same technique to initialize other constructors if more than one. We can therefore change the constructors of the program we had earlier using this syntax. 

Brick Unit - Header File: Brick.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick() : Length(0), Height(0), Thickness(0) {}

     TBrick(double L) : Length(L), Height(4.35), Thickness(3.05) {}

     TBrick(double L, double h, double t) : Length(L), Height(h), Thickness(t) {}

    double  getLength() const;

    void  setLength(const double l);

    double  getHeight() const;

    void  setHeight(const double h);

    double  getThickness() const;

    void  setThickness(const double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

The source file remains the same as above. The main() function would be implemented as follows. 

Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    // Calling the object using the default constructor

    TBrick Lott;

    Lott.ShowProperties();



    // This time, the program will use the constructor that has one argument

    TBrick Motto(6.12);

    Motto.ShowProperties();



    // The following object is supplied with arguments

    TBrick Hott(5.25, 3.55, 3.55);

    Hott.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce the following result:

Foundation Brick Properties

Length = 0.00

Height = 0.00

Thickness = 0.00

Cement Volume = 0.00

Foundation Brick Properties

Length = 6.12

Height = 4.35

Thickness = 3.05

Cement Volume = 21.63

Foundation Brick Properties

Length = 5.25

Height = 3.55

Thickness = 3.55

Cement Volume = 17.44



Press any key to continue...

If you do not want to implement these constructors in the header file, you can carry them to the source file, using the same syntax, like this:

Brick Unit - Header File: Brick.h

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick();

     TBrick(double L);

     TBrick(double L, double h, double t);

    double  getLength() const;

    void  setLength(const double l);

    double  getHeight() const;

    void  setHeight(const double h);

    double  getThickness() const;

    void  setThickness(const double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

Brick Unit - Source File: Brick.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;



#include "Bricks.h"

//---------------------------------------------------------------------------



 TBrick::TBrick() : Length(0), Height(0), Thickness(0)

{

}

//---------------------------------------------------------------------------

 TBrick::TBrick(double L) : Length(L), Height(4.35), Thickness(3.05)

{

}

//---------------------------------------------------------------------------

 TBrick::TBrick(double L, double h, double t)

    : Length(L), Height(h), Thickness(t)

{

}

//---------------------------------------------------------------------------

. . .
 

Initializing With Constructors

  1. To implement the both default and the complete constructors in the source file, change the listing of Students.h as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <string>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent() { FirstName = "John"; LastName = "Doe";
    
                                DayOfBirth = 1; MonthOfBirth = 1;
    
                                YearOfBirth = 1990;
    
                              }
    
         TStudent(string F, string L);        // Name Initializer
    
         TStudent(int DOB, int MOB, int YOB); // Initial Date of birth
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB)
    
                            {   FirstName    = fn;
    
                                LastName     = ln;
    
                                DayOfBirth   = DOB;
    
                                MonthOfBirth = MOB;
    
                                YearOfBirth  = YOB;
    
                            }
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  2. Make sure you change the implementation file as follows:

  3. To use the new technique of initializing the member variables, implement the constructors in the Students.cpp file as follows:

    //---------------------------------------------------------------------------
    
    
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(string FN, string LN)
    
    {
    
        FirstName    = FN;
    
        LastName     = LN;
    
        DayOfBirth   = 1;
    
        MonthOfBirth = 1;
    
        YearOfBirth  = 1985;
    
    }
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(int DOB, int MOB, int YOB)
    
    {                  
    
        FirstName    = "William";
    
        LastName     = "Smith";
    
        DayOfBirth   = DOB;
    
        MonthOfBirth = MOB;
    
        YearOfBirth  = YOB;
    
    }
    
    //---------------------------------------------------------------------------
    
    void  TStudent::Display()
    
    {
    
        // Display the characteristics of the student
    
        cout << "Characteristics of this student";
    
        cout << "\nFull Name: " << FirstName << " " << LastName;
    
        cout << "\nDate of Birth: " << DayOfBirth
    
             << "/" << MonthOfBirth << "/" << YearOfBirth << "\n";
    
    }
    
    //---------------------------------------------------------------------------
  4. Test the program and return to your programming environment.
  5. To initialize the member variables using parentheses, change the Students.h file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent() : FirstName("John"),
    
                                LastName("Doe"),
    
                                DayOfBirth(1),
    
                                MonthOfBirth(1),
    
                                YearOfBirth(1990)
    
                              {}
    
         TStudent(string F, string L);        // Name Initializer
    
         TStudent(int DOB, int MOB, int YOB); // Initial Date of birth
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB)
    
                            :   FirstName(fn),
    
                                LastName(ln),
    
                                DayOfBirth(DOB),
    
                                MonthOfBirth(MOB),
    
                                YearOfBirth(YOB)
    
                            {}
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  6. Test the program and return to your programming environment
  7. To use this initialization in the implementation file, change the Students.h file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <string>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent();
    
         TStudent(string F, string L);        // Name Initializer
    
         TStudent(int DOB, int MOB, int YOB); // Initial Date of birth
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB);
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  8. Change the Students.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent() : FirstName("John"), LastName("Doe"),
    
                                      DayOfBirth(1), MonthOfBirth(1),
    
                                      YearOfBirth(1990)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(string FN, string LN)
    
        : FirstName(FN), LastName(LN),
    
          DayOfBirth(1), MonthOfBirth(1), YearOfBirth(1985)
    
    {
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(int DOB, int MOB, int YOB)
    
        : FirstName("William"), LastName("Smith"),
    
          DayOfBirth(DOB), MonthOfBirth(MOB), YearOfBirth(YOB)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(string fn, string ln,
    
                                  int DOB, int MOB, int YOB)
    
        : FirstName(fn),
    
          LastName(ln),
    
          DayOfBirth(DOB),
    
          MonthOfBirth(MOB),
    
          YearOfBirth(YOB)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    void  TStudent::Display()
    
    {
    
        // Display the characteristics of the student
    
        cout << "Characteristics of this student";
    
        cout << "\nFull Name: " << FirstName << " " << LastName;
    
        cout << "\nDate of Birth: " << DayOfBirth
    
             << "/" << MonthOfBirth << "/" << YearOfBirth << "\n";
    
    }
    
    //---------------------------------------------------------------------------
  9. Press F9 to test the program and return to your programming environment.

The Copy Constructor

 

Copying an Object

After creating an object and assigning appropriate values to its members, you can perform any regular operation on it. Although this gets a little particular with objects, which will be expanded when learning about operator overloading, you can assign an object to another object. We have already learned:

How to assign Example
A value to a variable int a = 250;
The value of one variable to another NbrOfBoys = NbrOfGirls;
A value to an object’s member Video.Category = “Drama”

Assigning a variable to another is equivalent to making a copy of that variable. As you assign a variable to another, you can assign one object to another. Both objects must be recognizably equivalent to the compiler. Imagine you want to build the same brick twice. All you have to do is to assign one brick to another, which is take care of in the following main() function:

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------





int main()

{

    // Declaring one brick

    TBrick Hott(5.25, 3.55, 3.55);

    Hott.ShowProperties();

    cout << endl;



    // Assigning one brick to another

    TBrick Bosco = Hott;

    Bosco.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

Here is an example of running the program:

Foundation Brick Properties

Length = 5.25

Height = 3.55

Thickness = 3.55

Cement Volume = 17.44



Foundation Brick Properties

Length = 5.25

Height = 3.55

Thickness = 3.55

Cement Volume = 17.44



Press any key to continue...

Notice that both orders display the same thing.

Using a Copy Constructor

Besides the default constructor, the compiler creates another function method called the copy constructor. This is another special method that is used for operations such as copying an object into another.

Remember, we have seen that a variable can be initialized using the = symbol or the parentheses, as in the following example:

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

//---------------------------------------------------------------------------



int main()

{

    // Assigning a value to a variable using the = sign

    int CheeseSteak = 2;

    // Assigning a value using the parenthesis

    int TunaSalad(4);

    // Assigning one variable to another

    int TurkeyHam(TunaSalad);

    // Assignment with parenthesis

    double PriceCS(3.12); 

    double PriceTS = 2.95;

    // Assigning the price of one item to another

    double PriceTH(PriceTS);

    

    double TotalCS, TotalTS, TotalTH;

    TotalCS = CheeseSteak * PriceCS;

    TotalTS = TunaSalad * PriceTS;

    TotalTH = TurkeyHam * PriceTH;



    cout << "Total Order\n";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << CheeseSteak << " orders of Cheese Steak, Price = $"

         << TotalCS << "\n";

    cout << TunaSalad << " orders of Tuna Salad, Price = $"

         << TotalTS << endl;

    cout << TurkeyHam << " orders of Turkey Ham, Price = $" << TotalTH << endl;



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce:

Total Order

2 orders of Cheese Steak, Price = $6.24

4 orders of Tuna Salad, Price = $11.80

4 orders of Turkey Ham, Price = $11.80



Press any key to continue...

When you have two instances of an object such as:

Video Drama, Comedy;

you can assign one object to another like this:

Drama = Comedy;

This operation indeed assigns a copy of the Comedy Video to the Drama object. Behind the scenes, this transaction is handled by the copy constructor. Like the default constructor, the compiler automatically creates a copy constructor when an onbject is instantiated. Like the default constructor, you can explicitly create a copy constructor; it has a different syntax although it also holds the same name as the object. The syntax of the copy constructor.

ObjectName(ObjectName& Name);

The copy constructor takes one argument, which is the same as the object itself. When a copy is made, it holds and carries the building constructor of the object. This object is specified as the argument. As a copy whose value still resides with the object, this argument should be passed as a reference. As a copy, this argument should not be modified. It is only used to pass a copy of the object to the other objects that need it. Therefore, the argument should not be modified. As a result, it should be declared as a constant. The syntax of the copy constructor becomes:

ObjectName(const ObjectName& Name);

To copy one object to another, first create a copy constructor:

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH

//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick();

     TBrick(double L, double h, double t);

     TBrick(const TBrick &Brk);

    double  getLength() const;

    void  setLength(const double l);

    double  getHeight() const;

    void  setHeight(const double h);

    double  getThickness() const;

    void  setThickness(const double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

In the implementation, assign a member variable of the copy constructor to the equivalent member of the object:

//---------------------------------------------------------------------------

 TBrick::TBrick(const TBrick& B)

{

    Length    = B.Length;

    Height    = B.Height;

    Thickness = B.Thickness;

}

//---------------------------------------------------------------------------

Here is an example that uses a copy constructor to copy one order into another:

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Bricks.h"

//---------------------------------------------------------------------------



int main()

{

    TBrick  Beam(7.25, 4.85, 5.15), Hoyt;

    Beam.ShowProperties();

    cout << endl;



    // Create the other brick similar to the first

    // Assigning using the assignment operator

    Hoyt = Beam;

    Hoyt.ShowProperties();

    cout << endl;



    // Assigning using the parentheses

    TBrick Mollo(Beam);

    Hoyt.ShowProperties();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce:

Foundation Brick Properties

Length = 7.25

Height = 4.85

Thickness = 5.15

Cement Volume = 34.50



Foundation Brick Properties

Length = 7.25

Height = 4.85

Thickness = 5.15

Cement Volume = 34.50



Foundation Brick Properties

Length = 7.25

Height = 4.85

Thickness = 5.15

Cement Volume = 34.50



Press any key to continue...
 

Using the Copy Constructor

  1. To use the default copy constructor created by the compiler, change the content of the main() function as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    int main()
    
    {
    
        TStudent Student1("Pamela", "Wattson", 2, 18, 1988);
    
        Student1.Display();
    
        cout << endl;
    
    
    
        TStudent DefaultStudent;
    
        DefaultStudent.Display();
    
        cout << endl;
    
    
    
        TStudent DuplicateHer = Student1;
    
        DuplicateHer.Display();
    
    
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  2. Execute the program to test it and return to your programming environment.
  3. To explicitly create your own copy constructor, declare one in the header file as follows:
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent();
    
         TStudent(string F, string L);        // Name Initializer
    
         TStudent(int DOB, int MOB, int YOB); // Initial Date of birth
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB);
    
         TStudent(const TStudent& S);
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  4. Implement your copy constructor as follows:
     
    //---------------------------------------------------------------------------
    
     TStudent::TStudent(const TStudent& Stud)
    
        : FirstName(Stud.FirstName), LastName(Stud.LastName),
    
          DayOfBirth(Stud.DayOfBirth), MonthOfBirth(Stud.MonthOfBirth),
    
          YearOfBirth(Stud.YearOfBirth)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
  5. Test the program again and return to your programming environment.
  6. Save the project.

Destructors

 

Introduction 

As opposed to a constructor, a destructor is called when a program has finished using an instance of an object. A destructor does the cleaning behind the scenes. Like the default constructor, the compiler always create a default destructor if you don't create one. Like the default constructor, a destructor also has the same name as its object. This time, the name of the destructor starts with a tilde.

To create your own destructor, in the header file, type ~ followed by the name of the object. Here is an example:

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

     TBrick();

     TBrick(double L, double h, double t);

     TBrick(const TBrick &Brk);

     ~TBrick();

    double  getLength() const;

    void  setLength(const double l);

    double  getHeight() const;

    void  setHeight(const double h);

    double  getThickness() const;

    void  setThickness(const double t);

    double  CementVolume();

    void  ShowProperties();

private:

    double Length;

    double Height;

    double Thickness;

};

//---------------------------------------------------------------------------

#endif

As done with a default constructor, you don't need to put anything in the implementation of a destructor. In fact, when a program terminates, the compiler can itself destroy all of the objects and variables that your program has used. The only true time you will be concerned with destroying objects is if the objects were created dynamically, which we will learn when studying pointers.

You can implement your destructor in the header file by just providing it with empty parentheses:

//---------------------------------------------------------------------------

#ifndef BricksH

#define BricksH



//---------------------------------------------------------------------------

class TBrick

{

public:

    ...

     ~TBrick() {}

    ...

private:

    ...

};

//---------------------------------------------------------------------------

#endif

Otherwise, you can also implement it in the cpp file with empty parentheses. Here is an example:

//---------------------------------------------------------------------------

 TBrick::~TBrick()

{

}

//---------------------------------------------------------------------------

Using Destructors

  1. To illustrate the construction and destruction effects of an object, create a new Console Application named Library
  2. Change the content of the file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    class TBook
    
    {
    
    public:
    
        TBook(); // Constructor
    
        ~TBook(); // Destructor
    
        void Message() { cout << "\tI read the book\n"; }
    
    };
    
    //---------------------------------------------------------------------------
    
    TBook::TBook()
    
    {
    
        cout << "I see a book... Using the Constructor\n";
    
    }
    
    //---------------------------------------------------------------------------
    
    TBook::~TBook()
    
    {
    
        cout << "I close the book! Using the Destructor\n";
    
    }
    
    //---------------------------------------------------------------------------
    
    int main()
    
    {
    
        cout << "I am at the library\n";
    
        {
    
            TBook A;
    
        }
    
    
    
        cout << "\nI didn't like that book. I will try another\n\n";
    
        {
    
            TBook B;
    
            B.Message();
    
        }
    
    
    
        cout << "\nI am getting out of the library\n\n";
    
    
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  3. Execute the program to see the result:
     

    I am at the library
    
    I see a book... Using the Constructor
    
    I close the book! Using the Destructor
    
    
    
    I didn't like that book. I will try another
    
    
    
    I see a book... Using the Constructor
    
            I read the book
    
    I close the book! Using the Destructor
    
    
    
    I am getting out of the library
  4. Return to your programming environment

  5. Reopen the Students project from the Students2 folder.

  6. To create a destructor for our TStudent class, change the header file as follows:
     

    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream> 
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
         TStudent();
    
         TStudent(string F, string L);        // Name Initializer
    
         TStudent(int DOB, int MOB, int YOB); // Initial Date of birth
    
         TStudent(string fn, string ln,
    
                            int DOB, int MOB, int YOB);
    
         ~TStudent();
    
         TStudent(const TStudent& S);
    
        void  Display();
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  7. Implement the destructor in the Students.cpp file as follows:
     

    //---------------------------------------------------------------------------
    
     TStudent::~TStudent()
    
    {
    
    }
    
    //---------------------------------------------------------------------------
  8. Test the program and return to your programming environment.

========================================================

Combinations

In order to perform the various assignments it receives, the computer manipulates objects created in a program. In most significant applications, one object is not enough to accomplish a whole purpose. As we have learned that the use of one variable in a program is unrealistic, we can also combine various objects to create a more realistic and complete application.

There are various techniques used to mix objects in a program. To imitate the idea of combining different variables in a program, we will start by passing an object as a function argument, then we will be using various objects in the same program.

Objects and Functions

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 Borland C++ Builder, an object that is part of the C++ language, or one that you create.

The first thing you should do is create an object, unless you are using an existing one. Let’s build a conic tent. It is recognized by its radius, its height, the base area, and the area occupied by the texture. Our tent will look “long”, this is because I purposely included most of the techniques or features of building an object as we have learned so far. 

The header file creates a TCone object made of three constructors and a destructor. Since we will have private dimensions, we use get and set methods to take care of transactions between the object and the external world. We will also perform appropriate calculations.

Header File: Cone.h

//---------------------------------------------------------------------------



#ifndef ConeH

#define ConeH

//---------------------------------------------------------------------------

struct TCone

{

public:

    TCone();                     // Default constructor

    TCone(double r, double h);   // Constructor to initialize

    TCone(const TCone& c);       // Copy constructor

    ~TCone();                    // Destructor

    void setRadius(const double r) { Radius = r; }

    void setHeight(const double h) { Height = h; }

    double getRadius() const { return Radius; }

    double getHeight() const { return Height; }

    double Base() const;

    double TextureArea() const;

    double Volume() const;

private:

    double Radius;

    double Height;

};

//---------------------------------------------------------------------------

#endif

The source file is used to initialize the object (its member variables) and to perform the necessary calculations involved with the object.

Source File: Cone.cpp

//---------------------------------------------------------------------------

#include <math>

using namespace std;



#include "Cone.h"

//---------------------------------------------------------------------------



//const double PI = 3.1415926535;

//---------------------------------------------------------------------------

TCone::TCone()

    : Radius(0.00), Height(0.00)

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TCone::TCone(double r, double h)

    : Radius(r), Height(h)

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TCone::TCone(const TCone& c)

    : Radius(c.Radius), Height(c.Height)

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TCone::~TCone()

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

double TCone::Base() const

{

    // The area of the base of the cone

    return Radius * Radius * M_PI;

}

//---------------------------------------------------------------------------

double TCone::TextureArea() const

{

    // The area covered by the tissue that covers the tent

    double Radius2 = Radius * Radius;

    double Height2 = Height * Height;

    double SlantHeight = sqrt(Radius2 + Height2);

    return M_PI * Radius * SlantHeight;

}

//---------------------------------------------------------------------------

double TCone::Volume() const

{

    // The interior volume available for inhabiting the tent

    return (M_PI * Radius * Radius * Height) / 3;

}

//---------------------------------------------------------------------------

Once the object is built, you can call it from another function. As we have done with the main() function, you can call an object “as is” using the default constructor, which itself has the responsibility of using default values for its members:

Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Cone.h"

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCone Conic;



    cout << "A tent with default dimensions";

    cout << "\nRadius: " << Conic.getRadius();

    cout << "\nHeight: " << Conic.getHeight();

    cout << "\nBase Area: " << Conic.Base();

    cout << "\nTexture Area: " << Conic.TextureArea() << "\n";



    return 0;

}

//---------------------------------------------------------------------------

The program produces:

A tent with default dimensions

Radius: 0

Height: 0

Base Area: 0

Texture Area: 0



In the same way you can provide values for the object, using the right constructor or the right method:

Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Cone.h"

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCone Tone(25.55, 32.95);

    cout << "A tent with default dimensions";

    cout << "\nRadius:       " << Tone.getRadius();

    cout << "\nHeight:       " << Tone.getHeight();

    cout << "\nBase Area:    " << Tone.Base();

    cout << "\nTexture Area: " << Tone.TextureArea() << "\n";



    return 0;

}

//---------------------------------------------------------------------------

With an object as complete as our cone, you can let the user provide the dimensions for the tent:

Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Cone.h"

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCone Camper;

    double r, h;



    cout << "Specify the dimensions of the tent\n";

    cout << "Radius: ";

    cin >> r;

    cout << "Radius: ";

    cin >> h;



    Camper.setRadius(r);

    Camper.setHeight(h);

    

    cout << "\nA tent with user-defined dimensions";

    cout << "\nRadius:       " << Camper.getRadius();

    cout << "\nHeight:       " << Camper.getHeight();

    cout << "\nBase Area:    " << Camper.Base();

    cout << "\nTexture Area: " << Camper.TextureArea() << "\n";



    return 0;

}

//---------------------------------------------------------------------------

Which would produce, for example:

Specify the dimensions of the tent

Radius: 7.24

Radius: 4.88



A tent with user-defined dimensions

Radius:       7.24

Height:       4.88

Base Area:    164.675

Texture Area: 198.59



 

The Starting Object

  1. Start your programming environment if you didn’t yet.
  2. Create a C++ application and save the project in a folder called ROSH1. Save the starting unit as Main.cpp and the project as ROSH
  3. Create a new unit and save it as Students in the ROSH1 folder
  4. Change the Students.h file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
        TStudent();
    
        TStudent(string fn, string ln, int d, int m, int y);
    
        ~TStudent();
    
        string getFirstName() { return FirstName; }
    
        string getLastName() { return LastName; }
    
        int getDayOfBirth() { return DayOfBirth; }
    
        int getMonthOfBirth() { return MonthOfBirth; }
    
        int getYearOfBirth() { return YearOfBirth; }
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  5. Change the Students.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    TStudent::TStudent()
    
    {
    
        FirstName = "John";
    
        LastName = "Doe";
    
        DayOfBirth = 1;
    
        MonthOfBirth = 1;
    
        YearOfBirth = 1990;
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent(string fn, string ln, int d, int m, int y)
    
        : FirstName(fn), LastName(ln),
    
          DayOfBirth(d), MonthOfBirth(m), YearOfBirth(y)
    
    {
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::~TStudent()
    
    {
    
        //TODO: Add your source code here
    
    }
    
    //---------------------------------------------------------------------------
  6. Implement the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    
    
    int main(int argc, char* argv[])
    
    {
    
        TStudent St;
    
    
    
        cout << "Student with default values";
    
        cout << "\nFull Name: " << St.getFirstName()
    
             << " " << St.getLastName();
    
        cout << "\nDate of Birth: " << St.getDayOfBirth()
    
             << "/" << St.getMonthOfBirth()
    
             << "/" << St.getYearOfBirth();
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  7. To test the program, press F9:
     
    Student with default values
    
    Full Name: John Doe
    
    Date of Birth: 1/1/1990
    
    
    
    
  8. Return to your programming environment.
  9. To test the program with other values, change the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    int main(int argc, char* argv[])
    
    {
    
        TStudent St("Jeannette", "Smith", 12, 5, 1988);
    
    
    
        cout << "Student Information";
    
        cout << "\nFull Name: " << St.getFirstName()
    
             << " " << St.getLastName();
    
        cout << "\nDate of Birth: " << St.getDayOfBirth()
    
             << "/" << St.getMonthOfBirth()
    
             << "/" << St.getYearOfBirth();
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  10. Test the program
  11. Return to your programming environment.
  12. To let the user provide the values of an object, you can request these values from the user and fill out the object with those values. To see an example, change the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        string FN, LN;
    
        int Day, Month, Year;
    
        cout << "Enter the student's information\n";
    
        cout << "First Name: ";
    
        cin >> FN;
    
        cout << "Last Name: ";
    
        cin >> LN;
    
        cout << "Day of Birth: ";
    
        cin >> Day;
    
        cout << "Month of Birth: ";
    
        cin >> Month;
    
        cout << "Year of Birth: ";
    
        cin >> Year;
    
    
    
        TStudent St(FN, LN, Day, Month, Year);
    
    
    
        cout << "\nStudent Information";
    
        cout << "\nFull Name: " << St.getFirstName()
    
             << " " << St.getLastName();
    
        cout << "\nDate of Birth: " << St.getDayOfBirth()
    
             << "/" << St.getMonthOfBirth()
    
             << "/" << St.getYearOfBirth();
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  13. Test the program by press F9. Here is an example:
     
    Enter the student's information
    
    First Name: Gregory
    
    Last Name: Ballack
    
    Day of Birth: 22
    
    Month of Birth: 6
    
    Year of Birth: 1988
    
    
    
    Student Information
    
    Full Name: Gregory Ballack
    
    Date of Birth: 22/6/1988
    
    
    
    
  14. Return to your programming environment
  15. Writing values to an object allows the user to control the object. That’s why set methods are very valuable. To provide set methods, change the header file of the TStudents object as follows:

    Header File: Students.h
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
    public:
    
        TStudent();
    
        TStudent(string fn, string ln, int d, int m, int y);
    
        ~TStudent();
    
        void setFirstName(string f) { FirstName = f; }
    
        string getFirstName() { return FirstName; }
    
        void setLastName(string l) { LastName = l; }
    
        string getLastName() { return LastName; }
    
        void setDayOfBirth(int d) { DayOfBirth = d; }
    
        int getDayOfBirth() { return DayOfBirth; }
    
        void setMonthOfBirth(int m) { MonthOfBirth = m; }
    
        int getMonthOfBirth() { return MonthOfBirth; }
    
        void setYearOfBirth(int y) { YearOfBirth = y; }
    
        int getYearOfBirth() { return YearOfBirth; }
    
    
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  16. To request values of the Tstudents object, change the Main.cpp file as follows:

    Source File: Main.cpp
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        string FN, LN;
    
        int Day, Month, Year;
    
        TStudent St;
    
    
    
        cout << "Enter the student's information\n";
    
        cout << "First Name: ";
    
        cin >> FN;
    
        cout << "Last Name: ";
    
        cin >> LN;
    
        cout << "Day of Birth: ";
    
        cin >> Day;
    
        cout << "Month of Birth: ";
    
        cin >> Month;
    
        cout << "Year of Birth: ";
    
        cin >> Year;
    
    
    
        St.setFirstName(FN);
    
        St.setLastName(LN);
    
        St.setDayOfBirth(Day);
    
        St.setMonthOfBirth(Month);
    
        St.setYearOfBirth(Year);
    
    
    
        cout << "\nStudent Information";
    
        cout << "\nFull Name: " << St.getFirstName()
    
             << " " << St.getLastName();
    
        cout << "\nDate of Birth: " << St.getDayOfBirth()
    
             << "/" << St.getMonthOfBirth()
    
             << "/" << St.getYearOfBirth();
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  17. To test the program, press F9. Here is an example:
     
    Enter the student's information
    
    First Name: Juan
    
    Last Name: Gomez
    
    Day of Birth: 2
    
    Month of Birth: 2
    
    Year of Birth: 1991
    
    
    
    Student Information
    
    Full Name: Juan Gomez
    
    Date of Birth: 2/2/1991
    
    
    
    
  18. Return to your programming environment

An object as an Argument

After creating an object, it becomes a data type, sometimes referred to as a programmer defined data type. As an identifier, 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 main() function.

There are two techniques used to involve an object with a function. You can pass a member of an object as argument to a function, or you can pass the whole object as an argument. When passing an object as a parameter, you should be familiar with the construction of the object. Know its members and which ones you need to use. The code completion feature is highly useful in this circumstance.

Instead of displaying the characteristics of the tent in the main() function, we can use an external function to perform that assignment.

Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;

#include "Cone.h"

//---------------------------------------------------------------------------

void ShowTent(TCone c)

{

    cout << "Characteristics of this tent";

    cout << "\nRadius: " << c.getRadius();

    cout << "\nHeight: " << c.getHeight();

    cout << "\nBase Area: " << c.Base();

    cout << "\nTexture Area: " << c.TextureArea() << "\n";

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCone Tent;

    ShowTent(Tent);



    return 0;

}

//---------------------------------------------------------------------------

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:

Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Cone.h"

//---------------------------------------------------------------------------

void ShowTent(TCone c)

{

    cout << "\nCharacteristics of this tent";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nRadius:       " << c.getRadius();

    cout << "\nHeight:       " << c.getHeight();

    cout << "\nBase Area:    " << c.Base();

    cout << "\nTexture Area: " << c.TextureArea() << "\n";

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCone Tent;

    double r, h;



    cout << "Specify the dimensions of the tent\n";

    cout << "Radius: ";

    cin >> r;

    cout << "Height: ";

    cin >> h;



    Tent.setRadius(r);

    Tent.setHeight(h);

    ShowTent(Tent);



    return 0;

}

//---------------------------------------------------------------------------

Here is an example of running the program:

Specify the dimensions of the tent

Radius: 10.24

Height: 6.84



Characteristics of this tent

Radius:       10.24

Height:       6.84

Base Area:    329.42

Texture Area: 396.15



 

Using an Object as an Argument

  1. To use an object as argument, change the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        string FN, LN;
    
        int Day, Month, Year;
    
        void ShowStudent(TStudent s);
    
    
    
        cout << "Enter the student's information\n";
    
        cout << "First Name: "; cin >> FN;
    
        cout << "Last Name: "; cin >> LN;
    
        cout << "Day of Birth: "; cin >> Day;
    
        cout << "Month of Birth: "; cin >> Month;
    
        cout << "Year of Birth: "; cin >> Year;
    
    
    
        TStudent St(FN, LN, Day, Month, Year);
    
        ShowStudent(St);
    
    
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
    
    void ShowStudent(TStudent s)
    
    {
    
        cout << "\nStudent Registration";
    
        cout << "\nFull Name: "
    
             << s.getFirstName() << " " << s.getLastName();
    
        cout << "\nDate of Birth: " << s.getDayOfBirth() << "/"
    
             << s.getMonthOfBirth() << "/" << s.getYearOfBirth();
    
    }//---------------------------------------------------------------------------
  2. To test the program, press F9. Here is an example:
     
    Enter the student's information
    
    First Name: Joan
    
    Last Name: Lucent
    
    Day of Birth: 18
    
    Month of Birth: 4
    
    Year of Birth: 1986
    
    
    
    Student Registration
    
    Full Name: Joan Lucent
    
    Date of Birth: 18/4/1986
    
    
    
    
  3. Return to your programming environment

Objects and their External Interaction

 

Returning an Object

As a data type, you can use an object as returning value of a function. The issue this time is a little different. When returning an object, you should be familiar with the construction of the object, especially its constructorr. Since you will mostly return an object as complete as possible, the returned variable is a constructor. Therefore, when building the object inside of the function, make sure that the object can be used as a variable. Ask yourself if the object you are returning can be passed an argument to another function. Can it be used to display the complete properties of the object?

As opposed to requesting the dimensions of the tent from the main() function, we will use an external function to take care of that so that when the object is returned, we will trust that it can be used by another part of the program.

Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Cone.h"

//---------------------------------------------------------------------------





void Exit()

{

    

    

}

//---------------------------------------------------------------------------

void ShowTent(TCone c)

{

    cout << "\nCharacteristics of this tent";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nRadius:       " << c.getRadius();

    cout << "\nHeight:       " << c.getHeight();

    cout << "\nBase Area:    " << c.Base();

    cout << "\nTexture Area: " << c.TextureArea() << "\n";

}

//---------------------------------------------------------------------------

TCone ObtainDimensions()

{

    double r, h;



    cout << "Specify the dimensions of the tent\n";

    cout << "Radius: "; cin >> r;

    cout << "Radius: "; cin >> h;



    return TCone::TCone(r, h); // Returning the constructor

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCone Tent;



    Tent = ObtainDimensions();

    ShowTent(Tent);



    Exit();

    return 0;

}

//---------------------------------------------------------------------------

An example of running the program would produce:

Specify the dimensions of the tent

Radius: 8.44

Radius: 5.26



Characteristics of this tent

Radius:       8.44

Height:       5.26

Base Area:    223.79

Texture Area: 263.69



Another version of the ObainDimensions() function would consist of assigning the values of the member variables of the object to the right access methods:

Source File: Main.cpp

//---------------------------------------------------------------------------

TCone ObtainDimensions()

{

    double r, h;

    TCone Tonic;



    cout << "Specify the dimensions of the tent\n";

    cout << "Radius: "; cin >> r;

    cout << "Height: "; cin >> h;



    Tonic.setRadius(r);

    Tonic.setHeight(h);

    return Tonic;

}

//---------------------------------------------------------------------------

As another technique, you can first build the object by assembling the necessary member variables. Once the variables are gathered, you build an object based on those and return such an object from the function. Here is an example:

Source File: Main.cpp

//---------------------------------------------------------------------------

TCone ObtainDimensions()

{

    double r, h;



    cout << "Specify the dimensions of the tent\n";

    cout << "Radius: "; cin >> r;

    cout << "Height: "; cin >> h;



    TCone Copper(r, h);

    return Copper;

}

//---------------------------------------------------------------------------

Any of these techniques should allow you to return the desired object from a function and be able to use that object somewhere else, including displaying its properties using another function:

Specify the dimensions of the tent

Radius: 18.12

Height: 10.26



Characteristics of this tent

Radius:       18.12

Height:       10.26

Base Area:    1031.49

Texture Area: 1185.37



 

Returning an Object From a Function

  1. To apply an example of returning an object, change the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    
    
    
    
    
    
    int main(int argc, char* argv[])
    
    {
    
        TStudent Stud;
    
        TStudent Register();
    
        void ShowStudent(TStudent Grade1);
    
    
    
        Stud = Register();
    
        ShowStudent(Stud);
    
    
    
    
    
        
    
        
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
    
    void ShowStudent(TStudent s)
    
    {
    
        cout << "\nStudent Registration";
    
        cout << "\nFull Name: "
    
             << s.getFirstName() << " " << s.getLastName();
    
        cout << "\nDate of Birth: " << s.getDayOfBirth() << "/"
    
             << s.getMonthOfBirth() << "/" << s.getYearOfBirth();
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent Register()
    
    {
    
        string FN, LN;
    
        int Day, Month, Year;
    
        TStudent s;
    
    
    
        cout << "Enter the student's information\n";
    
        cout << "First Name: "; cin >> FN;
    
        cout << "Last Name: "; cin >> LN;
    
        cout << "Day of Birth: "; cin >> Day;
    
        cout << "Month of Birth: "; cin >> Month;
    
        cout << "Year of Birth: "; cin >> Year;
    
    
    
        s.setFirstName(FN);
    
        s.setLastName(LN);
    
        s.setDayOfBirth(Day);
    
        s.setMonthOfBirth(Month);
    
        s.setYearOfBirth(Year);
    
    
    
        return s;
    
    }
    
    //---------------------------------------------------------------------------
  2. Press F9 to test the program. Here is an example:
    Enter the student's information
    
    First Name: Jarrel
    
    Last Name: Jeremies
    
    Day of Birth: 2
    
    Month of Birth: 4
    
    Year of Birth: 1991
    
    
    
    Student Registration
    Full Name: Jarrel Jeremies
    Date of Birth: 2/4/1991
  3. Return to your programming environment

 Passing an Object by Reference

Since an object is a data type, it enjoys the features of the other, regular, variables. For example, instead of returning an object from a function, when this is not possible because of some circumstances, you can pass an object by reference. Like another variable, when an object is passed by reference, any alteration made on the object will be kept when the function exists. This feature allows you to declare a function as void but return a completely built object.

To pass an object by reference, use the ampersand between its name and the name of the argument inside of the function parentheses:

Source File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Cone.h"

//---------------------------------------------------------------------------





void Exit()

{

    

    

}

//---------------------------------------------------------------------------

void ShowTent(TCone c)

{

    cout << "\nCharacteristics of this tent";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "\nRadius:       " << c.getRadius();

    cout << "\nHeight:       " << c.getHeight();

    cout << "\nBase Area:    " << c.Base();

    cout << "\nTexture Area: " << c.TextureArea() << "\n";

}

//---------------------------------------------------------------------------

void ObtainDimensions(TCone& Tone)

{

    double r, h;



    cout << "Specify the dimensions of the tent\n";

    cout << "Radius: "; cin >> r;

    cout << "Radius: "; cin >> h;



    Tone.setRadius(r);

    Tone.setHeight(h);

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCone Tent;



    ObtainDimensions(Tent);

    ShowTent(Tent);



    Exit();

    

    return 0;

}

//---------------------------------------------------------------------------

Here is example of running the program:

Specify the dimensions of the tent

Radius: 5.12

Radius: 3.84



Characteristics of this tent

Radius:       5.12

Height:       3.84

Base Area:    82.35

Texture Area: 102.94



 

Passing an Object by Reference

  1. To pass an object as reference, change the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    
    
    
    
    int main(int argc, char* argv[])
    
    {
    
        TStudent Stud;
    
        void Register(TStudent&);
    
        void ShowStudent(TStudent Grade1);
    
    
    
        Register(Stud);
    
        ShowStudent(Stud);
    
    
    
        
    
        
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
    
    void Register(TStudent& S)
    
    {
    
        string FN, LN;
    
        int Day, Month, Year;
    
    
    
        cout << "Enter the student's information\n";
    
        cout << "First Name: "; cin >> FN;
    
        cout << "Last Name: "; cin >> LN;
    
        cout << "Day of Birth: "; cin >> Day;
    
        cout << "Month of Birth: "; cin >> Month;
    
        cout << "Year of Birth: "; cin >> Year;
    
    
    
        S.setFirstName(FN);
    
        S.setLastName(LN);
    
        S.setDayOfBirth(Day);
    
        S.setMonthOfBirth(Month);
    
        S.setYearOfBirth(Year);
    
    }
    
    //---------------------------------------------------------------------------
    
    void ShowStudent(TStudent s)
    
    {
    
        cout << "\nStudent Registration";
    
        cout << "\nFull Name: "
    
             << s.getFirstName() << " " << s.getLastName();
    
        cout << "\nDate of Birth: " << s.getDayOfBirth() << "/"
    
             << s.getMonthOfBirth() << "/" << s.getYearOfBirth();
    
    }
    
    //---------------------------------------------------------------------------
  2. Test the program and return to your programming environment

Friend Functions of a Class

Good programming techniques dictate that you should hide the variables used to store data of a class. This is done by declaring the member variables in the private section. Once a variable is hidden like that, only the members of the same class have access to it. The C++ language provides an alternative to this problem. Although you can still hide your variables, you can create special functions that have a “priviledged” access to the members of the private section of a class. These functions are not members of the class, they are just granted special access to the hidden member variables. Such functions are qualified as friends.

To declare a friend function, start with the friend keyword, followed by the return value, followed by the name of the function, its parentheses, and possibly the necessary arguments. Since a friend is not a function member of the object, you should provide access to the object, one way or another. When a function has been declared as a friend of a class, the class grants and controls the friendship.

The friend keyword is used only when declaring the friendly function. When defining the function, proceed as if it were a regularly declared function, omitting the friend keyword. Because friend functions are given special access, they can be declared anywhere in the class; but a good habit is to position them on top of the object just under the opening curly braket. This allow the compiler, you, and anybody who reads your code to have the list of friends of the class.

Here is a starting example. The Item class has two member variables that represent the quantity and the unit price. Both members are hidden in the private section, which means they cannot be seen outside of the class. Instead of creating a TotalPrice() member function, a friend function is declared so it can access the private members of the object:

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;



//---------------------------------------------------------------------------





class TForSale

{

    friend double TotalPrice(TForSale i);

public:

    TForSale(int q = 0, double p = 0.00);

private:

    int Qty;

    double UnitPrice;

};

//---------------------------------------------------------------------------

TForSale::TForSale(int Quantity, double Price)

    : Qty(Quantity), UnitPrice(Price)

{

}

//---------------------------------------------------------------------------

double TotalPrice(TForSale i)

{

    return i.Qty * i.UnitPrice;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TForSale item(12, 0.99);



    cout << "Total Price: $" << TotalPrice(item) << endl;



    

    

    return 0;

}

//---------------------------------------------------------------------------

An example of running the program would produce:

Total Price: $11.88



Although the above example comports only one function, an object can have as many friends as you see fit. For example, you can create a TTriangle object that has a Base and a Height private members, then declare two friend functions, one to calculate the perimeter and the other to calculate the area. The previous program was made of only one file. This time, you can separate the interface and the implementations in two files.

The object definition could appear as follows:

//---------------------------------------------------------------------------



#ifndef TriangleH

#define TriangleH

//---------------------------------------------------------------------------

struct TTriangle

{

    friend double Perimeter(TTriangle Tri);

    friend double Area(TTriangle Tri);



public:

    TTriangle(double B = 0.00, double H = 0.00);

    TTriangle(const TTriangle& t);

    ~TTriangle();

    double getBase() const;

    double getHeight() const;

private:

    double Base;

    double Height;

};

//---------------------------------------------------------------------------

#endif

Once the friends have been declared, you can define them in the header file of the object as if they were part of the interface. Here is an example:

//---------------------------------------------------------------------------



#ifndef TriangleH

#define TriangleH

//---------------------------------------------------------------------------

struct TTriangle

{

    friend double Perimeter(TTriangle Tri);

    friend double Area(TTriangle Tri);



public:

    TTriangle(double B = 0.00, double H = 0.00);

    TTriangle(const TTriangle& t);

    ~TTriangle();

    double getBase() const;

    double getHeight() const;

private:

    double Base;

    double Height;

};

//---------------------------------------------------------------------------

double Perimeter(TTriangle Tri)

{

    double RootOfHB = sqrt((Tri.Base * Tri.Base) + (Tri.Height * Tri.Height));



    return Tri.Base + Tri.Height + RootOfHB;

}

//---------------------------------------------------------------------------

double Area(TTriangle Tri)

{

    return Tri.Base * Tri.Height / 2;

}

//---------------------------------------------------------------------------

#endif

Just like all the functions and methods we have used so far, friend functions also can use the convention. To fastcall friend functions, type between the return type and the function name:

//---------------------------------------------------------------------------

#ifndef TriangleH

#define TriangleH

//---------------------------------------------------------------------------

struct TTriangle

{

    friend double Perimeter(TTriangle Tri);

    friend double Area(TTriangle Tri);



public:

    TTriangle(double B = 0.00, double H = 0.00);

    TTriangle(const TTriangle& t);

    ~TTriangle();

    double getBase() const;

    double getHeight() const;

private:

    double Base;

    double Height;

};

//---------------------------------------------------------------------------

double Perimeter(TTriangle Tri)

{

    double RootOfHB = sqrt((Tri.Base * Tri.Base) + (Tri.Height * Tri.Height));



    return Tri.Base + Tri.Height + RootOfHB;

}

//---------------------------------------------------------------------------

double Area(TTriangle Tri)

{

    return Tri.Base * Tri.Height / 2;

}

//---------------------------------------------------------------------------

#endif

Since you will usually choose to hide your hard work, you can define the friend functions in the source file of the object, as follows:

//---------------------------------------------------------------------------

#include <math>

using namespace std;



#include "Triangle.h"

//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

double Perimeter(TTriangle Tri)

{

    double RootOfHB = sqrt((Tri.Base * Tri.Base) + (Tri.Height * Tri.Height));



    return Tri.Base + Tri.Height + RootOfHB;

}

//---------------------------------------------------------------------------

double Area(TTriangle Tri)

{

    return Tri.Base * Tri.Height / 2;

}

//---------------------------------------------------------------------------

TTriangle::TTriangle(double B, double H)

    : Base(B), Height(H)

{

}

//---------------------------------------------------------------------------

TTriangle::TTriangle(const TTriangle& t)

    : Base(t.Base), Height(t.Height)

{

}

//---------------------------------------------------------------------------

TTriangle::~TTriangle()

{

}

//---------------------------------------------------------------------------

double TTriangle::getBase() const

{

    return Base;

}

//---------------------------------------------------------------------------

double TTriangle::getHeight() const

{

    return Height;

}

//---------------------------------------------------------------------------

Friends are called like any other regular global functions, by their names. They do not need to be qualified with the period operator. Therefore, they can be called by any function. They can be passed any variable declared from the friendly object; and as you know already, they have access to all members of the object. Here is a declaration of the TTriangle object in the main() function, We use an external function to display the characteristics of the object. Notice that this external function calls the friend functions of the class without qualifying them:

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Triangle.h"

//---------------------------------------------------------------------------





//---------------------------------------------------------------------------

void Characteristics(const TTriangle& T)

{

    cout << "Characteristics of the triangle\n";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "Base:      " << T.getBase() << endl;

    cout << "Height:    " << T.getHeight() << endl;

    cout << "Perimeter: " << Perimeter(T) << endl;

    cout << "Area:      " << Area(T) << endl;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TTriangle Trng(12.55, 10.85);



    Characteristics(Trng);



    

    

    return 0;

}

//---------------------------------------------------------------------------

Here is an example of running the program:

Characteristics of the triangle

Base:      12.55

Height:    10.85

Perimeter: 39.99

Area:      68.08



When a friend function does not modify the value(s) of the object’s member variable(s) it accesses, like a regular function, you should pass the object as a constant to protect your variables from erroneous modification. Here is an example:

//---------------------------------------------------------------------------

#ifndef TriangleH

#define TriangleH

//---------------------------------------------------------------------------

struct TTriangle

{

    friend double Perimeter(const TTriangle Tri);

    friend double Area(const TTriangle Tri);



public:

    TTriangle(double B = 0.00, double H = 0.00);

    TTriangle(const TTriangle& t);

    ~TTriangle();

    double getBase() const;

    double getHeight() const;

private:

    double Base;

    double Height;

};

//---------------------------------------------------------------------------

#endif

Of course, remember that the const keyword is used both when declaring the function and when defining it:

//---------------------------------------------------------------------------

double Perimeter(const TTriangle Tri)

{

    double RootOfHB = sqrt((Tri.Base * Tri.Base) + (Tri.Height * Tri.Height));



    return Tri.Base + Tri.Height + RootOfHB;

}

//---------------------------------------------------------------------------

double Area(const TTriangle Tri)

{

    return Tri.Base * Tri.Height / 2;

}

//---------------------------------------------------------------------------

When the compiler is accessing an object passed by value, there is overhead involved with going back and forth from the declaration to the definition of the object. One way you can improve the speed of this execution is to pass the object to its friend(s) as reference. This will allow the (friend) function(s) to access the object directly at its location in memory. Here is an example:

//---------------------------------------------------------------------------

#ifndef TriangleH

#define TriangleH

//---------------------------------------------------------------------------

struct TTriangle

{

    friend double Perimeter(TTriangle& Tri);

    friend double Area(TTriangle& Tri);



public:

    . . .

private:

    double Base;

    double Height;

};

//---------------------------------------------------------------------------

#endif

One more technique used to accelerate code execution when a (friend) function (or any function) does not modify the member variables of the object it receives is to not only pass it as a constant, but also by reference. Using this technique, although the function has access to the address of the object, the function cannot modify the object’s variables values. Here is our new header file:

//---------------------------------------------------------------------------

#ifndef TriangleH

#define TriangleH

//---------------------------------------------------------------------------

struct TTriangle

{

    friend double Perimeter(const TTriangle& Tri);

    friend double Area(const TTriangle& Tri);



public:

    . . .

private:

    double Base;

    double Height;

};

//---------------------------------------------------------------------------

#endif

When defining the (friend) functions, remember to use the same system of passing arguments as their declarations: Any function that does not modify the object argument it receives should have the object passed as a constant reference.

As an “acquaintance” of the object, a friend function is sometimes asked to perform assignments such as building and returning the object. This is the same technique used to return a complete object. To declare such a function, type the friend keyword, followed by the name of the class, followed by the name of the function and its parentheses. Possible arguments are an option. Here is an example:

//---------------------------------------------------------------------------

#ifndef TriangleH

#define TriangleH

//---------------------------------------------------------------------------

struct TTriangle

{

    friend TTriangle GetDimensions();

    friend double Perimeter(const TTriangle& Tri);

    friend double Area(const TTriangle& Tri);



public:

    TTriangle(double B = 0.00, double H = 0.00);

    TTriangle(const TTriangle& t);

    ~TTriangle();

    void setDimensions(const double b, const double h);

    double getBase() const;

    double getHeight() const;

private:

    double Base;

    double Height;

};

//---------------------------------------------------------------------------

#endif

The function would be defined as a regular function that returns the object:

//---------------------------------------------------------------------------

TTriangle GetDimensions()

{

    double x, y;



    cout << "Enter base: "; cin >> x;

    cout << "Enter height: "; cin >> y;



    return TTriangle(x, y);

}

//---------------------------------------------------------------------------

When calling this function, you can assign its returned value to a variable declared from the friendly object. Here is how it could be done in the main() function:

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Triangle.h"

//---------------------------------------------------------------------------





void Characteristics(const TTriangle& T)

{

    cout << "\nCharacteristics of the triangle\n";

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << "Base:      " << T.getBase() << endl;

    cout << "Height:    " << T.getHeight() << endl;

    cout << "Perimeter: " << Perimeter(T) << endl;

    cout << "Area:      " << Area(T) << endl;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TTriangle Slice;

    double b, h;



    Slice = GetDimensions();

    Characteristics(Slice);



    

    

    return 0;

}

//---------------------------------------------------------------------------
 

Using Friends of a Class

  1. To declare a friend function of a class, change the header file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
        friend TStudent Registration();
    
    public:
    
        TStudent();
    
        TStudent(string FN, string LN);
    
        TStudent(string fn, string ln, int d, int m, int y);
    
        TStudent(const TStudent& S);
    
        ~TStudent();
    
        void setFirstName(string f) { FirstName = f; }
    
        string getFirstName() { return FirstName; }
    
        void setLastName(string l) { LastName = l; }
    
        string getLastName() { return LastName; }
    
        void setDayOfBirth(int d) { DayOfBirth = d; }
    
        int getDayOfBirth() { return DayOfBirth; }
    
        void setMonthOfBirth(int m) { MonthOfBirth = m; }
    
        int getMonthOfBirth() { return MonthOfBirth; }
    
        void setYearOfBirth(int y) { YearOfBirth = y; }
    
        int getYearOfBirth() { return YearOfBirth; }
    
    
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  2. Change the source file as follows:
     
    //---------------------------------------------------------------------------
    
    
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    
    
    //---------------------------------------------------------------------------
    
    TStudent Registration()
    
    {
    
        TStudent S;
    
    
    
        // Notice that the function has access to the
    
        // private members of the class
    
        cout << "Enter the student's information\n";
    
        cout << "First Name: "; cin >> S.FirstName;
    
        cout << "Last Name: "; cin >> S.LastName;
    
        cout << "Day of Birth: "; cin >> S.DayOfBirth;
    
        cout << "Month of Birth: "; cin >> S.MonthOfBirth;
    
        cout << "Year of Birth: "; cin >> S.YearOfBirth;
    
    
    
        return S;
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent()
    
    {
    
        FirstName = "John";
    
        LastName = "Doe";
    
        DayOfBirth = 1;
    
        MonthOfBirth = 1;
    
        YearOfBirth = 1990;
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent(string FN, string LN)
    
        : FirstName(FN), LastName(LN),
    
          DayOfBirth(1), MonthOfBirth(1), YearOfBirth(1990)
    
    {
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent(string fn, string ln, int d, int m, int y)
    
        : FirstName(fn), LastName(ln),
    
          DayOfBirth(d), MonthOfBirth(m), YearOfBirth(y)
    
    {
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent(const TStudent& Stud)
    
        : FirstName(Stud.FirstName),
    
          LastName(Stud.LastName),
    
          DayOfBirth(Stud.DayOfBirth),
    
          MonthOfBirth(Stud.MonthOfBirth),
    
          YearOfBirth(Stud.YearOfBirth)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::~TStudent()
    
    {
    
        //TODO: Add your source code here
    
    }
    
    //---------------------------------------------------------------------------
  3. Change the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        TStudent Stud;
    
        void StudentInfo(TStudent Grade1);
    
    
    
        Stud = Registration();
    
        StudentInfo(Stud);
    
    
    
        
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
    
    void StudentInfo(TStudent s)
    
    {
    
        cout << "\nStudent Registration";
    
        cout << "\nFull Name: "
    
             << s.getFirstName() << " " << s.getLastName();
    
        cout << "\nDate of Birth: " << s.getDayOfBirth() << "/"
    
             << s.getMonthOfBirth() << "/" << s.getYearOfBirth();
    
    }
    
    //---------------------------------------------------------------------------
  4. Test the program. Here is an example:
     
    Enter the student's information
    
    First Name: Josh
    
    Last Name: Annett
    
    Day of Birth: 10
    
    Month of Birth: 12
    
    Year of Birth: 1985
    
    
    
    Student Registration
    
    Full Name: Josh Annett
    
    Date of Birth: 10/12/1985
  5. Return to your programming environment
  6. To pass a class to a friend as a reference, change the declaration of the friend function in the header file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
        friend void Registration(TStudents &Student);
    
    
    
    public:
    
        . . .
    
    
    
    private:
    
        . . .
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  7. Change the implementation of the friend function as follows:
     
    //---------------------------------------------------------------------------
    
    void Registration(TStudents &S)
    
    {
    
        // Notice that the function has access to the
    
        // private members of the class
    
        cout << "Enter the student's information\n";
    
        cout << "First Name: "; cin >> S.FirstName;
    
        cout << "Last Name: "; cin >> S.LastName;
    
        cout << "Day of Birth: "; cin >> S.DayOfBirth;
    
        cout << "Month of Birth: "; cin >> S.MonthOfBirth;
    
        cout << "Year of Birth: "; cin >> S.YearOfBirth;
    
    }
    
    //---------------------------------------------------------------------------
  8. Test the program and return to your programming environment

Mixing Different Objects in the Same Program

Before using different objects in your program, they must be known to the compiler. These objects could be part of the operating system, they could be part of C++ Builder, they could be defined as C++ objects, or you can create your own. To start, we will learn how to use objects that we create.

An office supplies store has hired you to write a program that will allow customers to create their own business labels using a computer located somewhere in the store. We will use two objects for our program. TDimensions will define the dimensions of the label and another object called TLabelType will define the paper quality.

A classic label has dimensions set by a length and a width. When a user or another part of the program calls the label, it mostly uses constructors; and we will use them. The first constructor takes no argument; it is used to set the default dimensions for the label. The second constructor will make sure that the supplied dimensions, if any, are correct. To protect our dimensions, the length and the width will be private; we will provide access methods to get the dimensions:

//---------------------------------------------------------------------------

#ifndef RectangleH

#define RectangleH

//---------------------------------------------------------------------------

class TRectangle

{

public:

    TRectangle();

    TRectangle(double L, double W);

    TRectangle(const TRectangle& Rect);

    ~TRectangle();

    void setLength(double L) { Length = L; }

    void setHeight(double H) { Height = H; }

    double getLength() { return Length; }

    double getHeight() { return Height; }

    double Perimeter(double Length, double Height);

    double Area(double Length, double Height);

private:

    double Length;

    double Height;

};

//---------------------------------------------------------------------------

#endif

The source file initializes the object, controls the dimensions, and calculates the area:

//---------------------------------------------------------------------------



using namespace std;



#include "Rectangle.h"

//---------------------------------------------------------------------------



TRectangle::TRectangle()

    : Length(3.25), Height(2.55)

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TRectangle::TRectangle(double L, double H)

    : Length(L), Height(H)

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TRectangle::TRectangle(const TRectangle& r)

    : Length(r.Length), Height(r.Height)

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TRectangle::~TRectangle()

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

double TRectangle::Perimeter(double x, double y)

{

    return 2 * (x + y);

}

//---------------------------------------------------------------------------

double TRectangle::Area(double x, double y)

{

    return x * y;

}

//---------------------------------------------------------------------------

The second object specifies the characteristics of the label including its model number, its color, whether the label will use a removable or a non-removable adhesive. Once again, we will use two constructors for the same reasons as above.

Header File: LabelType.h

//---------------------------------------------------------------------------

#ifndef LabelTypeH

#define LabelTypeH

#include <string>

using namespace std;

//---------------------------------------------------------------------------

class TLabelType

{

public:

    TLabelType();

    TLabelType(long m, string c, string n, string a);

    ~TLabelType();

    void setModelNumber(long m) { ModelNumber = m; }

    void setName(string n) { Name = n; }

    void setColor(string c) { Color = c; }

    void setAdhesive(string a) { Adhesive = a; }

    long getModelNumber() const;

    string getName() const;

    string getColor() const;

    string getAdhesive() const;

private:

    long ModelNumber;

    string Name;

    string Color;

    string Adhesive;

};

//---------------------------------------------------------------------------

#endif

The implementation file of the TLabelType object is used to initialize an object and control its properties.

Source File: LabelType.cpp

//---------------------------------------------------------------------------



using namespace std;



#include "LabelType.h"

//---------------------------------------------------------------------------



TLabelType::TLabelType()

    : ModelNumber(0), Color("White"),

      Name("None"), Adhesive("Not Specified")

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TLabelType::TLabelType(long m, string c, string n, string a)

    : ModelNumber(m), Color(c), Name(n), Adhesive(a)

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

TLabelType::~TLabelType()

{

    //TODO: Add your source code here

}

//---------------------------------------------------------------------------

long TLabelType::getModelNumber() const

{

    return ModelNumber;

}

//---------------------------------------------------------------------------

string TLabelType::getName() const

{

    return Name;

}

//---------------------------------------------------------------------------

string TLabelType::getColor() const

{

    return Color;

}

//---------------------------------------------------------------------------

string TLabelType::getAdhesive() const

{

    return Adhesive;

}

//---------------------------------------------------------------------------

Once you have objects, you can declare each when desired and supply its properties if needed. In our main() function, we will first call the TDimension and the TLabelType objects using empty contructors. Whenever any function or object calls an object without specifying the properties, each object will display its default values:

Main File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Rectangle.h"

#include "LabelType.h"

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TRectangle Dim;

    TLabelType LabelType;



    cout << "A label with default characteristics";

    cout << "\nDimensions: " << Dim.getLength()

         << " * " << Dim.getHeight();

    cout << "\nArea:       " << Dim.Area(Dim.getLength(), Dim.getHeight());

    cout << "\nModel No.:  " << LabelType.getModelNumber();

    cout << "\nModel Name: " << LabelType.getName();

    cout << "\nColor:      " << LabelType.getColor();

    cout << "\nAdhesive:   " << LabelType.getAdhesive();



    

    

    return 0;

}

//---------------------------------------------------------------------------

The program would produce:

A label with default characteristics

Dimensions: 3.25 * 2.55

Area:       8.2875

Model No.:  0

Model Name: None

Color:      White

Adhesive:   Not Specified



The program can also provide the values of each object, using their methods:

Main File: Main.cpp

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

#include "Rectangle.h"

#include "LabelType.h"

//---------------------------------------------------------------------------





//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TRectangle Dim(4.55, 2.25);

    TLabelType LabelType(25442, "Mandarin", "One Touch", "Non-Removable");



    cout << "An example label";

    cout << "\nDimensions: " << Dim.getLength()

         << " * " << Dim.getHeight();

    cout << "\nArea:       " << Dim.Area(Dim.getLength(), Dim.getHeight());

    cout << "\nModel No.:  " << LabelType.getModelNumber();

    cout << "\nModel Name: " << LabelType.getName();

    cout << "\nColor:      " << LabelType.getColor();

    cout << "\nAdhesive:   " << LabelType.getAdhesive();



    

    

    return 0;

}

//---------------------------------------------------------------------------

This time, the program would display different values:

An example label

Dimensions: 4.55 * 2.25

Area:       10.2375

Model No.:  25442

Model Name: One Touch

Color:      Mandarin

Adhesive:   Non-Removable



 

Combining Objects

  1. To process a semi-complete registration for a student, consisting of a complete address, change the Students.h file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef StudentsH
    
    #define StudentsH
    
    #include <iostream>
    
    //---------------------------------------------------------------------------
    
    class TStudent
    
    {
    
        friend void Registration(TStudent &Student);
    
    
    
    public:
    
        TStudent();
    
        TStudent(string FN, string LN);
    
        TStudent(string fn, string ln, int d, int m, int y);
    
        TStudent(const TStudent& S);
    
        ~TStudent();
    
        void setFirstName(string f) { FirstName = f; }
    
        string getFirstName() const { return FirstName; }
    
        void setLastName(string l) { LastName = l; }
    
        string getLastName() const { return LastName; }
    
        void setDayOfBirth(int d) { DayOfBirth = d; }
    
        int getDayOfBirth() const { return DayOfBirth; }
    
        void setMonthOfBirth(int m) { MonthOfBirth = m; }
    
        int getMonthOfBirth() const { return MonthOfBirth; }
    
        void setYearOfBirth(int y) { YearOfBirth = y; }
    
        int getYearOfBirth() const { return YearOfBirth; }
    
        void setAddress(string a) { Address = a; }
    
        string getAddress() const { return Address; }
    
        void setCity(string c) { City = c; }
    
        string getCity() const { return City; }
    
        void setState(string s) { State = s; }
    
        string getState() const { return State; }
    
        void setZIPCode(string z) { ZIPCode = z; }
    
        string getZIPCode() const { return ZIPCode; }
    
        void setCountry(string c) { Country = c; }
    
        string getCountry() const { return Country; }
    
    
    
    private:
    
        string FirstName;
    
        string LastName;
    
        int DayOfBirth;
    
        int MonthOfBirth;
    
        int YearOfBirth;
    
        string Address;
    
        string City;
    
        string State;
    
        string ZIPCode;
    
        string Country;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  2. Change the Students.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    
    
    using namespace std;
    
    
    
    #include "Students.h"
    
    //---------------------------------------------------------------------------
    
    
    
    
    
    //---------------------------------------------------------------------------
    
    void Registration(TStudent &S)
    
    {
    
        // Notice that the function has access to the
    
        // private members of the class
    
        cout << "Enter the student's information\n";
    
        cout << "First Name:     "; cin >> S.FirstName;
    
        cout << "Last Name:      "; cin >> S.LastName;
    
        cout << "Day of Birth:   "; cin >> S.DayOfBirth;
    
        cout << "Month of Birth: "; cin >> S.MonthOfBirth;
    
        cout << "Year of Birth:  "; cin >> S.YearOfBirth;
    
        cout << "Address: ";
    
        cin >> ws;
    
        getline(cin, S.Address);
    
        cout << "City:    ";
    
        getline(cin, S.City);
    
        cout << "State:   ";
    
        getline(cin, S.State);
    
        cout << "ZIPCode: ";
    
        getline(cin, S.ZIPCode);
    
        cout << "Country: ";
    
        getline(cin, S.Country);
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent()
    
    {
    
        FirstName    = "John";
    
        LastName     = "Doe";
    
        DayOfBirth   = 1;
    
        MonthOfBirth = 1;
    
        YearOfBirth  = 1990;
    
        Address      = "123 Main Street";
    
        City         = "Old Town";
    
        State        = "This State";
    
        ZIPCode      = "01234-0001";
    
        Country      = "USA";
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent(string FN, string LN)
    
        : FirstName(FN), LastName(LN),
    
          DayOfBirth(1), MonthOfBirth(1), YearOfBirth(1990),
    
          Address("123 Main Street"),
    
          City("This State"),
    
          State("Unkown"),
    
          ZIPCode("00001-0001"),
    
          Country("USA")
    
    {
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent(string fn, string ln, int d, int m, int y)
    
        : FirstName(fn), LastName(ln),
    
          DayOfBirth(d), MonthOfBirth(m), YearOfBirth(y),
    
          Address("123 Main Street"),
    
          City("This State"),
    
          State("Unkown"),
    
          ZIPCode("00001-0001"),
    
          Country("USA")
    
    {
    
        
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::TStudent(const TStudent& Stud)
    
        : FirstName(Stud.FirstName),
    
          LastName(Stud.LastName),
    
          DayOfBirth(Stud.DayOfBirth),
    
          MonthOfBirth(Stud.MonthOfBirth),
    
          YearOfBirth(Stud.YearOfBirth),
    
          Address(Stud.Address),
    
          City(Stud.City),
    
          State(Stud.State),
    
          ZIPCode(Stud.ZIPCode),
    
          Country(Stud.Country)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    TStudent::~TStudent()
    
    {
    
        //TODO: Add your source code here
    
    }
    
    //---------------------------------------------------------------------------
  3. Create a new 
  4. class called TGrades object and change the Grades.h file as follows:
     
    //---------------------------------------------------------------------------
    
    
    
    #ifndef GradesH
    
    #define GradesH
    
    //---------------------------------------------------------------------------
    
    #endif
    
    //---------------------------------------------------------------------------
    
    class TGrades
    
    {
    
        friend void GetGrades(TGrades&);
    
    public:
    
        TGrades();
    
        TGrades(double e, double s, double h,
    
                           double g, double c, double o,
    
                           double m, double p, double r, double t);
    
        ~TGrades();
    
        void setEnglish(double e) { English = e; }
    
        double getEnglish() { return English; }
    
        void setSecondLng(double s) { SecondLng = s; }
    
        double getSecondLng() { return SecondLng; }
    
        void setHistory(double h) { History = h; }
    
        double getHistory() { return History; }
    
        void setGeography(double g) { Geography = g; }
    
        double getGeography() { return Geography; }
    
        void setChemistry(double c) { Chemistry = c; }
    
        double getChemistry() { return Chemistry; }
    
        void setSociology(double o) { Sociology = o; }
    
        double getSociology() { return Sociology; }
    
        void setMath(double m) { Math = m; }
    
        double getMath() { return Math; }
    
        void setCompSc(double p) { CompSc = p; }
    
        double getCompSc() { return CompSc; }
    
        void setMorale(double a) { Morale = a; }
    
        double getMorale() { return Morale; }
    
        void setSports(double t) { Sports = t; }
    
        double getSports() { return Sports; }
    
        double CalcTotal();
    
        double CalcMean();
    
    private:
    
        double English;
    
        double SecondLng;
    
        double History;
    
        double Geography;
    
        double Chemistry;
    
        double Sociology;
    
        double Math;
    
        double CompSc;
    
        double Morale;
    
        double Sports;
    
    };
  5. To implement the TGrades object, change the Grades.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    
    
    #include "Grades.h"
    
    //---------------------------------------------------------------------------
    
    
    
    TGrades::TGrades()
    
        : English(0.00),
    
          SecondLng(0.00),
    
          History(0.00),
    
          Geography(0.00),
    
          Chemistry(0.00),
    
          Sociology(0.00),
    
          Math(0.00),
    
          CompSc(0.00),
    
          Morale(0.00),
    
          Sports(0.00)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    TGrades::TGrades(double e, double s, double h,
    
                                double g, double c, double o,
    
                                double m, double p, double r, double t)
    
        : English(e),
    
          SecondLng(s),
    
          History(h),
    
          Geography(g),
    
          Chemistry(c),
    
          Sociology(o),
    
          Math(m),
    
          CompSc(p),
    
          Morale(r),
    
          Sports(t)
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    TGrades::~TGrades()
    
    {
    
        //TODO: Add your source code here
    
    }
    
    //---------------------------------------------------------------------------
    
    double TGrades::CalcTotal()
    
    {
    
        double Total = English + SecondLng + History +
    
                       Geography + Chemistry + Sociology +
    
                       Math + CompSc + Morale + Sports;
    
    
    
        return Total;
    
    }
    
    //---------------------------------------------------------------------------
    
    double TGrades::CalcMean()
    
    {
    
        return CalcTotal() / 10;
    
    }
    
    //---------------------------------------------------------------------------
    
    void GetGrades(TGrades& Student)
    
    {
    
        cout << "English:         "; cin >> Student.English;
    
        cout << "Second Language: "; cin >> Student.SecondLng;
    
        cout << "History:         "; cin >> Student.History;
    
        cout << "Geography:       "; cin >> Student.Geography;
    
        cout << "Chemistry:       "; cin >> Student.Chemistry;
    
        cout << "Sociology:       "; cin >> Student.Sociology;
    
        cout << "Mathematics:     "; cin >> Student.Math;
    
        cout << "Comp Sciences:   "; cin >> Student.CompSc;
    
        cout << "Morale:          "; cin >> Student.Morale;
    
        cout << "Sports:          "; cin >> Student.Sports;
    
    }
    
    //---------------------------------------------------------------------------
  6. To use both objects in the same program, implement the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    #include <iomanip>
    
    using namespace std;
    
    #include "Students.h"
    
    #include "Grades.h"
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        TStudent Stud;
    
        TGrades Grade;
    
        void StudentInfo(TStudent Grade1);
    
        void ShowGrades(TGrades d);
    
    
    
        cout << "Student Registration\n";
    
        Registration(Stud);
    
        cout << endl;
    
        cout << "Student Grades\n";
    
        GetGrades(Grade);
    
    
    
        system("cls");
    
    
    
        StudentInfo(Stud);
    
        ShowGrades(Grade);
    
    
    
        
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
    
    void StudentInfo(TStudent s)
    
    {
    
        cout << "====================================";
    
        cout << "\nStudent Report";
    
        cout << "\n------------------------------------";
    
        cout << "\nStudent Registration";
    
        cout << "\nFull Name: "
    
             << s.getFirstName() << " " << s.getLastName();
    
        cout << "\nDate of Birth: " << s.getDayOfBirth() << "/"
    
             << s.getMonthOfBirth() << "/" << s.getYearOfBirth();
    
        cout << "\nAddress:   " << s.getAddress()
    
             << "\n           " << s.getCity() << ", " << s.getState()
    
             << ", " << s.getZIPCode()
    
             << "\n           " << s.getCountry();
    
    }
    
    //---------------------------------------------------------------------------
    
    void ShowGrades(TGrades d)
    
    {
    
        cout << setiosflags(ios::fixed) << setprecision(2);
    
        cout << "\n------------------------------------";
    
        cout << "\n\tEnglish:       " << d.getEnglish();
    
        cout << "\n\tLanguage 2:    " << d.getSecondLng();
    
        cout << "\n\tHistory:       " << d.getHistory();
    
        cout << "\n\tGeography:     " << d.getGeography();
    
        cout << "\n\tChemistry:     " << d.getChemistry();
    
        cout << "\n\tSociology:     " << d.getSociology();
    
        cout << "\n\tMathematics:   " << d.getMath();
    
        cout << "\n\tComp Sciences: " << d.getCompSc();
    
        cout << "\n\tMorale:        " << d.getMorale();
    
        cout << "\n\tSports:        " << d.getSports();
    
        cout << "\n------------------------------------";
    
        cout << "\n\tTotal: " << d.CalcTotal() << "\tMean: " << d.CalcMean();
    
        cout << "\n====================================";
    
    }
    
    //---------------------------------------------------------------------------
  7. To test the program, press F9. Here is an example:
     
    First Screen:
     
    Student Registration
    
    Enter the student's information
    
    First Name:     Paul
    
    Last Name:      Delamarre
    
    Day of Birth:   28
    
    Month of Birth: 2
    
    Year of Birth:  1986
    
    Address: 8402 Norton Hwy #D12
    
    City:    Silver Spring
    
    State:   MD
    
    ZIPCode: 20910-4412
    
    Country: USA
    
    
    
    Student Grades
    
    English:         12.50
    
    Second Language: 10.25
    
    History:         14.50
    
    Geography:       13.00
    
    Chemistry:       15.00
    
    Sociology:       12.50
    
    Mathematics:     16.50
    
    Comp Sciences:   17.25
    
    Morale:          14.00
    
    Sports:          15.50

    Second Screen:
     

    ====================================
    
    Student Report
    
    ------------------------------------
    
    Student Registration
    
    Full Name: Paul Delamarre
    
    Date of Birth: 28/2/1986
    
    Address:   8402 Norton Hwy #D12
    
               Silver Spring, MD, 20910-4412
    
               USA
    
    ------------------------------------
    
            English:       12.50
    
            Language 2:    10.25
    
            History:       14.50
    
            Geography:     13.00
    
            Chemistry:     15.00
    
            Sociology:     12.50
    
            Mathematics:   16.50
    
            Comp Sciences: 17.25
    
            Morale:        14.00
    
            Sports:        15.50
    
    ------------------------------------
    
            Total: 141.00   Mean: 14.10
    
    ====================================
  8. Return to your programming environment
========================================================================================

Classes and Arrays

An Array of Object Variables

We have learned to treat classes and structures as normal variables including creating an object by declaring a variable. We can define an object as follows:

#include <iostream>
using namespace std;

struct Point
{
    char Letter;
    int x;
    int y;
};

int main()
{
	Point location;

    location.Letter = 'D';
    location.x      =  5;
    location.y      = -2;

    cout << "Point Location " << location.Letter << "("
         << location.x << ", " << location.y << ");" << endl;

	return 0;
}

This would produce:

Point Location D(5, -2);

Remember that you can also use the typedef keyword to customize the name of a data type. For example, the Point class can be type-defined as follows:

typedef Point Coordinate;

Coordinate location;

As you would declare an array of variables, you can also declare an array of objects and manipulate each member of the array as if it were a regular variable. To do this, type the name of the class, followed by a valid C++ name for the variable, and followed by a dimension included in square brackets. Here is an example:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

};



int main()

{

	Point coordinates[4];



	return 0;

}

Using the typedef keyword, you can create a common name that would represent an array of objects. This can be done as follows:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

};



int main()

{

    typedef Point Points[4];

    Points coordinates;



    return 0;

}

In this case, the name Points means the same thing as declaring an array of 4 Point variables.

After declaring a variable as an array of objects, each member of the array has its own value you can assign, change, or retrieve. To get the value stored in a member variable of a member of an array, access it using its index. For example, to access the value of the third member variable of the first member of the above array, you could write the following:

coordinates[0].y;

Initializing an Array of Objects

There are various ways you can initialize an array of objects. You can initialize the variable as a whole, when declaring it. Still, there are at least two ways you can initialize a variable when declaring it. To do this, assign an opening and closing curly brackets combination to the variable. Inside the curly brackets, provide a list of the values of each member variable object, first in the order they appear in the class, second in the incremental order of the array. Here is an example:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

};



int main()

{

	Point Coordinates[4] = {'P', -4,  0, 'Q', -3, -2,

				'L',  5,  1, 'M', 2,  6};



    cout << "Point Coordinates";

    cout << "\n" << Coordinates[0].Letter << "("

         << Coordinates[0].x << ", " << Coordinates[0].y << ");";

    cout << "\n" << Coordinates[1].Letter << "("

         << Coordinates[1].x << ", " << Coordinates[1].y << ");";

    cout << "\n" << Coordinates[2].Letter << "("

         << Coordinates[2].x << ", " << Coordinates[2].y << ");";

    cout << "\n" << Coordinates[3].Letter << "("

         << Coordinates[3].x << ", " << Coordinates[3].y << ");\n";

	return 0;

}

This would produce:

Point Coordinates

P(-4, 0);

Q(-3, -2);

L(5, 1);

M(2, 6);

Another technique you can use, which would make the initialization easier to read, consists of including the values of each member of the array in its own set of curly brackets. It would be done as follows:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

};



int main()

{

	Point Coordinates[4] = { {'P', -4,  0}, {'Q', -3, -2},

				 {'L',  5,  1}, {'M', 2,  6}};



    cout << "Point Coordinates";

    cout << "\n" << Coordinates[0].Letter << "("

         << Coordinates[0].x << ", " << Coordinates[0].y << ");";

    cout << "\n" << Coordinates[1].Letter << "("

         << Coordinates[1].x << ", " << Coordinates[1].y << ");";

    cout << "\n" << Coordinates[2].Letter << "("

         << Coordinates[2].x << ", " << Coordinates[2].y << ");";

    cout << "\n" << Coordinates[3].Letter << "("

         << Coordinates[3].x << ", " << Coordinates[3].y << ");\n";

	return 0;

}

In our introduction to Classes, we also saw that you could declare an instance of a structure when creating it. This was done by providing a name for the variable between the closing curly bracket and the semi-colon. In the same way, when declaring such a variable, you can initialize it directly. Here is an example:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

} Coordinates[4] = {'P', -4,  0, 'Q', -3, -2,'L',  5,  1, 'M', 2,  6};



int main()

{

    cout << "Point Coordinates";

    cout << "\n" << Coordinates[0].Letter << "("

         << Coordinates[0].x << ", " << Coordinates[0].y << ");";

    cout << "\n" << Coordinates[1].Letter << "("

         << Coordinates[1].x << ", " << Coordinates[1].y << ");";

    cout << "\n" << Coordinates[2].Letter << "("

         << Coordinates[2].x << ", " << Coordinates[2].y << ");";

    cout << "\n" << Coordinates[3].Letter << "("

         << Coordinates[3].x << ", " << Coordinates[3].y << ");\n";

	return 0;

}

In the same way, you can initialize the array when creating the variable:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

} Coordinates[4] = { {'P', -4,  0}, {'Q', -3, -2},

		     {'L',  5,  1}, {'M', 2,  6}};



int main()

{

    cout << "Point Coordinates";

    cout << "\n" << Coordinates[0].Letter << "("

         << Coordinates[0].x << ", " << Coordinates[0].y << ");";

    cout << "\n" << Coordinates[1].Letter << "("

         << Coordinates[1].x << ", " << Coordinates[1].y << ");";

    cout << "\n" << Coordinates[2].Letter << "("

         << Coordinates[2].x << ", " << Coordinates[2].y << ");";

    cout << "\n" << Coordinates[3].Letter << "("

         << Coordinates[3].x << ", " << Coordinates[3].y << ");\n";

	return 0;

}

The above techniques of initialization are convenient for small objects, traditionally used as C structures. The other technique you can use, also convenient for an array of a more elaborate object, consists of initializing each member of the array. To do this, you assign a value to each member of the object. This can be done as follows:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

};



int main()

{

    Point Coordinates[2];



    Coordinates[0].Letter = 'P';

    Coordinates[0].x = -4;

    Coordinates[0].y =  0;

    Coordinates[1].Letter = 'Q';

    Coordinates[1].x = -3;

    Coordinates[1].y = -2;



    cout << "Point Coordinates";

    cout << "\n" << Coordinates[0].Letter << "("

         << Coordinates[0].x << ", " << Coordinates[0].y << ");";

    cout << "\n" << Coordinates[1].Letter << "("

         << Coordinates[1].x << ", " << Coordinates[1].y << ");\n";



	return 0;

}

Here is an example of running the program:

Point Coordinates

P(-4, 0);

Q(-3, -2);

Once you have declared and initialized an array of objects, you can use the values of its member variables as you see fit. For example, from the above Point class, you can request the coordinates of two points, write an equation that calculates their distance or one that gets their slope, and display it to the user. This can be done as follows:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

};



int main()

{

    Point Points[2];

    double Slope;



    cout << "Enter the coordinates of the points\n";

    cout << "x1 = "; cin >> Points[0].x;

    cout << "y1 = "; cin >> Points[0].y;

    cout << "x2 = "; cin >> Points[1].x;

    cout << "y2 = "; cin >> Points[1].y;

    

    Points[0].Letter = 'A';

    Points[1].Letter = 'B';

    

    if( Points[0].x != Points[1].x )

        Slope = (Points[1].y - Points[0].y) / (Points[1].x - Points[0].x);

    else

        Slope = 0.00;



    cout << "The slope of " << Points[0].Letter << "("

         << Points[0].x << ", " << Points[0].y << ") and "

         << Points[1].Letter << "(" << Points[1].x << ", "

         << Points[1].y << ") is " << Slope << endl;



	return 0;

}

Here is an example of running the program:

Enter the coordinates of the points

x1 = -2

y1 = 3

x2 = 1

y2 = -3

The slope of A(-2, 3) and B(1, -3) is -2
 

An Array of Objects as Argument

Like a regular data type, an array of objects can be passed as an argument to a function. To do this, when declaring and when implementing the function, provide the array in the parentheses of the function as you would do with any other regular variable. Here is an example that takes and processes an argument that is an array of objects:

void ProcessCoordinates(Point points[])

{

    cout << "Enter the coordinates of four points\n";

    cout << "x1 = "; cin >> points[0].x;

    cout << "y1 = "; cin >> points[0].y;

    cout << "x2 = "; cin >> points[1].x;

    cout << "y2 = "; cin >> points[1].y;

    cout << "x3 = "; cin >> points[2].x;

    cout << "y3 = "; cin >> points[2].y;

    cout << "x4 = "; cin >> points[3].x;

    cout << "y4 = "; cin >> points[3].y;

}

The above function was using an array whose dimension you know. If you do not know or cannot predict the dimension of an array, you can/should/must pass an additional argument that holds the number of members of the array.

When calling a function that takes a single-dimension array of objects, the name of the argument is sufficient to the compiler. Other than this, you can apply all the other rules we learned for arrays of regular data types:

#include <iostream>

using namespace std;



struct Point

{

    char Letter;

    int x;

    int y;

};



void ProcessCoordinates(Point points[]);

void DisplayCoordinates(Point points[], const int size);



int main()

{

    Point coordinates[4];



    ProcessCoordinates(coordinates);

    cout << endl;

    DisplayCoordinates(coordinates, 4);



    return 0;

}



void ProcessCoordinates(Point points[])

{

    cout << "Enter the coordinates of four points\n";

    cout << "x1 = "; cin >> points[0].x;

    cout << "y1 = "; cin >> points[0].y; points[0].Letter = 'A';

    cout << "x2 = "; cin >> points[1].x;

    cout << "y2 = "; cin >> points[1].y; points[1].Letter = 'B';

    cout << "x3 = "; cin >> points[2].x;

    cout << "y3 = "; cin >> points[2].y; points[2].Letter = 'C';

    cout << "x4 = "; cin >> points[3].x;

    cout << "y4 = "; cin >> points[3].y; points[3].Letter = 'D';

}



void DisplayCoordinates(Point points[], const int size)

{

    cout << "Point Coordinates";

    for(int i = 0; i < size; i++)

        cout << "\n" << points[i].Letter << "("

             << points[i].x << ", " << points[i].y << ");";

}

Here is an example of running the program:

Enter the coordinates of four points

x1 = -1

y1 = 5

x2 = -2

y2 = -4

x3 = 3

y3 = 5

x4 = 2

y4 = -4



Point Coordinates

A(-1, 5);

B(-2, -4);

C(3, 5);

D(2, -4);

Classes and Pointers

 

Declaring a Pointer to an Object

Header File: cone.h

//---------------------------------------------------------------------------

#ifndef ConeH

#define ConeH                                                                

//---------------------------------------------------------------------------

class Cone

{

private:

    double _rad;

    double _hgt;

public:

    Cone();

    Cone(double radius, double height);

    Cone(const Cone& c);

    ~Cone();

    void setRadius(const double radius) { _rad = radius; }

    void setHeight(const double height) { _hgt = height; }

    double getRadius() const { return _rad; }

    double getHeight() const { return _hgt; }

    double CalculateBaseArea() const;

    double CalculateLateralArea() const;

    double CalculateTotalArea() const;

    double CalculateVolume() const;

};

//---------------------------------------------------------------------------

#endif

Source File: cone.cpp

//---------------------------------------------------------------------------

#include <math.h>

#include "Cone.h"

//using namespace std;

//---------------------------------------------------------------------------

Cone::Cone()

    : _rad(0.00), _hgt(0.00)

{

    

}

//---------------------------------------------------------------------------

Cone::Cone(double r, double h)

    : _rad(r), _hgt(h)

{

    

}

//---------------------------------------------------------------------------

Cone::Cone(const Cone& c)

    : _rad(c._rad), _hgt(c._hgt)

{

    

}

//---------------------------------------------------------------------------

Cone::~Cone()

{

    

}

//---------------------------------------------------------------------------

double Cone::CalculateBaseArea() const

{

    // The area of the base of the cone

    return _rad * _rad * 3.14159;

}

//---------------------------------------------------------------------------

double Cone::CalculateLateralArea() const

{

    // The area covered by the tissue that covers the tent

    double radius2 = _rad * _rad;

    double height2 = _hgt * _hgt;

    double slantHeight = sqrt(radius2 + height2);

    return 3.14159 * _rad * slantHeight;

}

//---------------------------------------------------------------------------

double Cone::CalculateTotalArea() const

{

    return CalculateBaseArea() + CalculateLateralArea();

}

//---------------------------------------------------------------------------

double Cone::CalculateVolume() const

{

    // The interior volume available for inhabiting the tent

    return (3.14159 * _rad * _rad * _hgt) / 3;

}

//---------------------------------------------------------------------------

Like a regular data type, you can declare a class as a pointer, you can pass it to a function as a reference or as a pointer, and you can dynamically create an instance of a class. To declare a pointer to a class, type its name, followed by an asterisk and followed by a name for the variable. Here is an example:

Cone *pCone;

Like a pointer to a regular data type, after declaring a pointer to a class, you should let the compiler know what variable the pointer is pointing to. This can easily be done by assigning the address of an existing variable as follows:

#include <iostream>

#include "cone.h"

using namespace std;



int main()

{

    Cone iceCone;

    Cone *pCone = &iceCone;

  

    double radius, height;



    cout << "Enter the cone's dimensions\n";

    cout << "Radius: ";

    cin >> radius;

    cout << "Height: ";

    cin >> height;



    pCone->setRadius(radius);

    pCone->setHeight(height);



    cout << "Cone's Characteristics";

    cout << "\nRadius:       " << pCone->getRadius();

    cout << "\nHeight:       " << pCone->getHeight();

    cout << "\nBase Area:    " << pCone->CalculateBaseArea();

    cout << "\nTotal Area:   " << pCone->CalculateTotalArea();

    cout << "\nTexture Area: " << pCone->CalculateLateralArea() << endl;



    return 0;

}

Here is an example of running the program:

Enter the cone's dimensions

Radius: 38.44

Height: 20.72

Cone's Characteristics

Radius:       38.44

Height:       20.72

Base Area:    4642.12

Total Area:   9915.67

Texture Area: 5273.55
 

Dynamic Objects

One of the advantages of using pointers is that they give you the ability to use memory only as needed. This is done by using the asterisk * and the new operators. The syntax of declaring a pointer to an object is:

ClassName* VariableName = new ClassName;

The ClassName is the class whose variable you want to declare. It could be in the program or one that shipped with the compiler. Once again, the asterisk lets the compiler know that the class is declared as a pointer. The variable name follows the same rules we have applied to other variables so far.

There are two main ways you can provide values to the member variables of your dynamic object. You can request their values from the user, from another object or function, or you can initialize the variable. Still there are at least two ways you can initialize the variable. When declaring it, since you would be using a constructor to build the object, you can use the constructor that takes the number of values you want to initialize. Consider the above Cone class. This class provides three constructors, one of which takes two arguments to initialize a complete Cone variable. You can use this constructor when using the new operator. In the parentheses, provide a value for each member variable. Here is an example:

#include <iostream>

#include "cone.h"

using namespace std;



int main()

{

    Cone *pCone = new Cone(25.55, 20.15);



    cout << "Cone's Characteristics";

    cout << "\nRadius:       " << pCone->getRadius();

    cout << "\nHeight:       " << pCone->getHeight();

    cout << "\nBase Area:    " << pCone->CalculateBaseArea();

    cout << "\nTotal Area:   " << pCone->CalculateTotalArea();

    cout << "\nTexture Area: " << pCone->CalculateLateralArea() << endl;



	return 0;

}

This would produce:

Cone's Characteristics

Radius:       25.55

Height:       20.15

Base Area:    2050.84

Total Area:   4662.71

Texture Area: 2611.88

If you want to use, or have used, the default constructor to create the object, you can then use one of its methods to initialize the variable. Here is an example:

#include <iostream>

#include "cone.h"

using namespace std;



int main()

{

    Cone *pCone = new Cone();



    pCone->setRadius(25.55);

    pCone->setHeight(20.15);



    cout << "Cone's Characteristics";

    cout << "\nRadius:       " << pCone->getRadius();

    cout << "\nHeight:       " << pCone->getHeight();

    cout << "\nBase Area:    " << pCone->CalculateBaseArea();

    cout << "\nTotal Area:   " << pCone->CalculateTotalArea();

    cout << "\nTexture Area: " << pCone->CalculateLateralArea() << endl;



	return 0;

}

Of course, at any time, you can change the values of the pointer using either one of its constructors or its methods. After using a variable that was declared using the new operator, you can reclaim the memory space it was using. This is done with the delete operator.

Here is an example:

#include <iostream>

#include "cone.h"

using namespace std;



int main()

{

    Cone *pCone = new Cone();



    pCone->setRadius(25.55);

    pCone->setHeight(20.15);



    cout << "Cone's Characteristics";

    cout << "\nRadius:       " << pCone->getRadius();

    cout << "\nHeight:       " << pCone->getHeight();

    cout << "\nBase Area:    " << pCone->CalculateBaseArea();

    cout << "\nTotal Area:   " << pCone->CalculateTotalArea();

    cout << "\nTexture Area: " << pCone->CalculateLateralArea() << endl;



    pCone = new Cone(44.42, 35.72);



    cout << "\nCone's Characteristics";

    cout << "\nRadius:       " << pCone->getRadius();

    cout << "\nHeight:       " << pCone->getHeight();

    cout << "\nBase Area:    " << pCone->CalculateBaseArea();

    cout << "\nTotal Area:   " << pCone->CalculateTotalArea();

    cout << "\nTexture Area: " << pCone->CalculateLateralArea() << endl;



	return 0;

}

This would produce:

Cone's Characteristics

Radius:       25.55

Height:       20.15

Base Area:    2050.84

Total Area:   4662.71

Texture Area: 2611.88



Cone's Characteristics

Radius:       44.42

Height:       35.72

Base Area:    6198.79

Total Area:   14153.2

Texture Area: 7954.38

Pointers to Arrays of Objects

Instead of using one pointer to an object, you can declare an array of pointers to object. The syntax used is:

ClassName *VariableName[Dimension];

The ClassName must be an existing object. You can use your own object or one that shipped with the compiler. After the asterisk operator, type a valid name for a C++ variable. The dimension, which is (an estimate of) the number of elements of the array, is included in square brackets.

After declaring the variable, you can initialize each member of the array using the new operator. This operator allocates enough memory space for the member of the array. This means that the initialization with the new operator can be followed by an actual initialization of the member variables of the array.

To initialize a member of the array, you have various options. You must first call the new operator for each member of the array. Once again, you can use one of the constructors. Consider the above Cone object. We saw that one of its constructors took two arguments to create an object. You can use such a constructor to initialize a member of the array. Here are examples:

#include <iostream>

#include "cone.h"

using namespace std;



int main()

{

    Cone *pCone[3];



    pCone[0] = new Cone(25.55, 20.15);

    pCone[1] = new Cone(12.44, 18.62);

    pCone[2] = new Cone(48.12, 38.84);



    cout << "Cone's Characteristics\n";

    for(int i = 0; i < 3; i++)

    {

        cout << "\n - Cone No. " << i + 1 << " -";

        cout << "\nRadius:       " << pCone[i]->getRadius();

        cout << "\nHeight:       " << pCone[i]->getHeight();

        cout << "\nBase Area:    " << pCone[i]->CalculateBaseArea();

        cout << "\nTotal Area:   " << pCone[i]->CalculateTotalArea();

        cout << "\nTexture Area: " << pCone[i]->CalculateLateralArea() << endl;

    }



	return 0;

}

This would produce:

Cone's Characteristics



 - Cone No. 1 -

Radius:       25.55

Height:       20.15

Base Area:    2050.84

Total Area:   4662.71

Texture Area: 2611.88



 - Cone No. 2 -

Radius:       12.44

Height:       18.62

Base Area:    486.172

Total Area:   1361.33

Texture Area: 875.159



 - Cone No. 3 -

Radius:       48.12

Height:       38.84

Base Area:    7274.46

Total Area:   16622.9

Texture Area: 9348.43

If you had already created some objects and want to use their values, you can assign the desired variable to the member of the array of your choice. Here are examples:

#include <iostream>

#include "cone.h"

using namespace std;



int main()

{

    Cone *pCone[3];

    Cone conic(66.14, 50.82);

    Cone *iceCreamCone = new Cone(8.74, 6.82);



    pCone[0] = &conic;

    pCone[1] = iceCreamCone;

    pCone[2] = new Cone(48.12, 38.84);



    cout << "Cone's Characteristics\n";

    for(int i = 0; i < 3; i++)

    {

        cout << "\n - Cone No. " << i + 1 << " -";

        cout << "\nRadius:       " << pCone[i]->getRadius();

        cout << "\nHeight:       " << pCone[i]->getHeight();

        cout << "\nBase Area:    " << pCone[i]->CalculateBaseArea();

        cout << "\nTotal Area:   " << pCone[i]->CalculateTotalArea();

        cout << "\nTexture Area: " << pCone[i]->CalculateLateralArea() << endl;

    }



    return 0;

}

This would produce:

Cone's Characteristics



 - Cone No. 1 -

Radius:       66.14

Height:       50.82

Base Area:    13742.9

Total Area:   31074.1

Texture Area: 17331.3



 - Cone No. 2 -

Radius:       8.74

Height:       6.82

Base Area:    239.979

Total Area:   544.373

Texture Area: 304.395



 - Cone No. 3 -

Radius:       48.12

Height:       38.84

Base Area:    7274.46

Total Area:   16622.9

Texture Area: 9348.43

Another technique you can use is to first allocate memory space for a member of the array, then use one of the methods of the object to initialize that particular member of the array. This can be taken care of with set methods.

After using the array, you can delete each of its members using the delete operator. Here is an example:

#include <iostream>

#include "cone.h"

using namespace std;



int main()

{

    Cone *pCone[3];



    pCone[0] = new Cone;

    pCone[0]->setRadius(25.55);

    pCone[0]->setHeight(20.15);

                               

    pCone[1] = new Cone;

    pCone[1]->setRadius(12.44);

    pCone[1]->setHeight(18.62);

    

    pCone[2] = new Cone;

    pCone[2]->setRadius(48.12);

    pCone[2]->setHeight(38.84);



    cout << "Cone's Characteristics\n";

    for(int i = 0; i < 3; i++)

    {

        cout << "\n - Cone No. " << i + 1 << " -";

        cout << "\nRadius:       " << pCone[i]->getRadius();

        cout << "\nHeight:       " << pCone[i]->getHeight();

        cout << "\nBase Area:    " << pCone[i]->CalculateBaseArea();

        cout << "\nTotal Area:   " << pCone[i]->CalculateTotalArea();

        cout << "\nTexture Area: " << pCone[i]->CalculateLateralArea() << endl;

    }



    delete pCone[0];

    delete pCone[1];

    delete pCone[2];



    return 0;

}
 

An Object Passed as Pointer

To pass an object as pointer, when declaring and when implementing the object, use the asterisk operator between the class name and the variable name. Consequently, when defining the function, access the members of the object using the arrow operator:

void RequestDimensions(Cone* cn)

{

    double Radius, Height;



    cout << "Enter the cone's dimensions\n";

    cout << "Radius: ";

    cin >> Radius;

    cout << "Height: ";

    cin >> Height;



    cn->setRadius(Radius);

    cn->setHeight(Height);

}

When calling such a function, if the variable was declared as a regular item, in the parentheses of the function, call the variable using the reference operator:

#include <iostream>

#include "cone.h"

using namespace std;



void RequestDimensions(Cone* cn)

{

    double Radius, Height;



    cout << "Enter the cone's dimensions\n";

    cout << "Radius: ";

    cin >> Radius;

    cout << "Height: ";

    cin >> Height;



    cn->setRadius(Radius);

    cn->setHeight(Height);

}



int main()

{

    Cone typeCone;



    RequestDimensions(&typeCone);



    cout << "\nCone's Characteristics";

    cout << "\nRadius:       " << typeCone.getRadius();

    cout << "\nHeight:       " << typeCone.getHeight();

    cout << "\nBase Area:    " << typeCone.CalculateBaseArea();

    cout << "\nTotal Area:   " << typeCone.CalculateTotalArea();

    cout << "\nTexture Area: " << typeCone.CalculateLateralArea();



    return 0;

}

Here is an example of running the program:

Enter the cone's dimensions

Radius: 24.58

Height: 20.64



Cone's Characteristics

Radius:       24.58

Height:       20.64

Base Area:    1898.07

Total Area:   4376.58

Texture Area: 2478.5

As you may have realized, when an argument is passed as pointer, if the function modifies its value, the object would be altered. This has the same effect as passing an object by reference because, once more, the function has access to the memory location of the argument. Consequently, there is an advantage of speed when passing an argument as pointer. If, on the other hand, you do not want the function to modify the value of the argument, you can pass it as a constant pointer. Here is an example:

#include <iostream>

#include "cone.h"

using namespace std;



void RequestDimensions(Cone*);

void ShowCharacteristics(const Cone *pCone);



int main()

{

    Cone typeCone;



    RequestDimensions(&typeCone);



    ShowCharacteristics(&typeCone);



    return 0;

}



void RequestDimensions(Cone* cn)

{

    double Radius, Height;



    cout << "Enter the cone's dimensions\n";

    cout << "Radius: ";

    cin >> Radius;

    cout << "Height: ";

    cin >> Height;



    cn->setRadius(Radius);

    cn->setHeight(Height);

}



void ShowCharacteristics(const Cone *pCone)

{

    cout << "\nCone's Characteristics";

    cout << "\nRadius:       " << pCone->getRadius();

    cout << "\nHeight:       " << pCone->getHeight();

    cout << "\nBase Area:    " << pCone->CalculateBaseArea();

    cout << "\nTotal Area:   " << pCone->CalculateTotalArea();

    cout << "\nTexture Area: " << pCone->CalculateLateralArea();

}

 

 

Classes and Pointers to Functions

 

A Pointer to Function as a Member Variable

When studying pointers to functions, we learned to use a programmer's type-defined declaration to create an alias to a pointer to function. We used an example such as the following:

typedef double (*Multiply)(const double a);

With this declaration, the word Multiply can be used in place of a function that takes a double-precision value as argument and the function returns a double. We learned that such a Multiply name could be used to declare a variable that in fact would be used as a function. Based on this feature of the C++ language, the Multiply name can also be used to declare a member variable of an object. Such a member variable would be interpreted as a function. The declaration can be done as follows:

typedef double (*Multiply)(const double a);



struct TSquare

{

    Multiply Perimeter;

};

As done with the regular pointer to function, you do not implement the Perimeter method. In fact, so far, the compiler does not know what to do with the Perimeter member. Therefore, you must formally define a function that can implement the behavior that the Perimeter member is supposed to use. Such a function can be defined as follows:

double Perimetre(const double x)

{

    return x * 4;

}

Even with this definition of the Perimetre() function, there is no relationship between the Perimeter member of the TSquare class and the Perimetre() independent function, and the compiler does not see any relationship between them. This means that, until you join these two functions, the compiler would not know what to do with the member of the object. To use the Perimeter member of the TSquare object, you should first assign it an appropriate function that has the same signature as its alias. Then you can use the member of the class as if it were a regular method of the object. Here is an example of how this would be done:

//---------------------------------------------------------------------------

#include <iostream>

using namespace std;



//---------------------------------------------------------------------------

                                                      

typedef double (*Multiply)(const double a);

//---------------------------------------------------------------------------

struct TSquare

{

    Multiply Perimeter;

};

//---------------------------------------------------------------------------

double Perimetre(const double x)

{

    return x * 4;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TSquare Sqr;



    double Side = 25.55;

    Sqr.Perimeter = Perimetre;



    cout << "Square Characteristics";

    cout << "\nSide:      " << Side;

    cout << "\nPerimeter: " << Sqr.Perimeter(Side);



    

    

    return 0;

}

//---------------------------------------------------------------------------

Using this same approach, you can declare different types of pointers to function as you see fit and using the function signature of your choice. Keep in mind that, when an alias is used to declare a variable, because it is declaring a variable type and not a function, you cannot create various aliases with the same name. This causes a name conflict, even if you try using different function signatures. Here is an example:

//---------------------------------------------------------------------------

#include <iostream>



using namespace std;



//---------------------------------------------------------------------------



typedef double (*Multiply)(const double a);

typedef double (*Multiple)(const double x, const double y);

//---------------------------------------------------------------------------

struct TSquare

{

    Multiply Perimeter;

    Multiple Area;

};

//---------------------------------------------------------------------------

double Perimetre(const double x)

{

    return x * 4;

}

//---------------------------------------------------------------------------

double Surface(const double x, const double y)

{

    return x * y;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TSquare Sqr;



    double Side = 25.55;

    Sqr.Perimeter = Perimetre;

    Sqr.Area = Surface;



    cout << "Square Characteristics";

    cout << "\nSide:      " << Side;

    cout << "\nPerimeter: " << Sqr.Perimeter(Side);

    cout << "\nArea:      " << Sqr.Area(Side, Side);



    

    

    return 0;

}

//---------------------------------------------------------------------------

Pointers to Method

Many of the functions and classes you will be using when creating applications are from already existing libraries. The idea is to reduce your efforts and be a little faster and productive. You also will be creating a lot of functions and classes. Once you have created such functionalities, there will be no reason to always write the same code over and over again. For example, if you had previously created a class that can process a rectangle object, it would not be good to create a new rectangle class when you need one, you can just refer to one of your classes that can do the job. Code reuse is a tremendous feature of object oriented programming and you should take advantage of it.

We have just learned that you can use a pointer to function to declare a member or members of an object. We learned that, to do this, you must have a function that would implement the desired functionality of the member variable. What about the reverse? Can you create a pointer to a method and use it as a declarable type?

The C++ language allows you to use a member function of an object as pointer to function. To do this, the C++ language require that the name of the method be fully qualified because the compiler would need to know which object possesses that method. The syntax you would use to create such an alias is:

typedef ReturnType (ClassName::*VariableName)(Arguments, if any);

The typedef keyword lets the compiler know that you are creating an alias. The return type must be either a regular data type (int, char, double and their variants) or an object (class a struct). Between the first parentheses, provide the name of the object (class or structure) that "owns" the method whose alias you want to create. The VariableName is a valid C++ name of a variable (and not the function member). If the method takes argument(s), you can provide the type(s) of argument(s) in the second parentheses. If the method does not take any argument, leave the (second) parentheses empty.

Imagine you create a special class that would regularly help you perform arithmetic operations. Such a class can be structured as follows:

class TArithmetic

{

public:

    double Addition(double Value1, double Value2);

    double Subtraction(double Value1, double Value2);

    double Multiplication(double Value1, double Value2);

    double Division(double Numerator, double Denominator);

};

Imagine that, in your program, you want to perform an addition of two values and produce a result. You can create an alias to the Addition method as follows:

typedef double (TArithmetic::*Add)(double x, double y);

With this definition, the word Add can be used in place of a function that takes two double-precision values as arguments and returns a real value. To use this alias, you must point it to the desired method of the object. This can be done as follows:

Add Plus = &TArithmetic::Addition;

Now, the name Plus can be used to call the Addition() method of the TArithmetic class. Of course, because using a class, you must first declare a variable from it. Because Plus is in fact a pointer, you must call it as such. Here is an example of how Plus can be used as a function:

//---------------------------------------------------------------------------

#include <iostream>



using namespace std;





//---------------------------------------------------------------------------



class TArithmetic

{

public:

    double Addition(double Value1, double Value2);

    double Subtraction(double Value1, double Value2);

    double Multiplication(double Value1, double Value2);

    double Division(double Numerator, double Denominator);

};

//---------------------------------------------------------------------------

double TArithmetic::Addition(double Val1, double Val2)

{

    return Val1 + Val2;

}

//---------------------------------------------------------------------------

double TArithmetic::Subtraction(double Val1, double Val2)

{

    return Val1 - Val2;

}

//---------------------------------------------------------------------------

double TArithmetic::Multiplication(double Val1, double Val2)

{

    return Val1 * Val2;

}

double TArithmetic::Division(double Num, double Den)

{

    if( Den == 0 )

        return 0;

    // else is implied

    return Num / Den;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    typedef double (TArithmetic::*Add)(double x, double y);

    

    TArithmetic Oper;

    Add Plus = &TArithmetic::Addition;



    double APlusB = (Oper.*Plus)(244, 125);



    cout << "244 + 125 = " << APlusB;



    

    

    return 0;

}

//---------------------------------------------------------------------------

When we studied pointers to functions, we learned to declare them as follows:

double (*Add)(double x, double y);

It would be a good idea to use this alias as a pointer to methods of a class. This could be done as follows:

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    double (*Add)(double x, double y);

    

    TArithmetic Oper;

    Add = Oper.Addition;



    double APlusB = Add(244, 125);



    cout << "244 + 125 = " << APlusB;



    

    

    return 0;

}

//---------------------------------------------------------------------------
 

Objects and Pointers to Function

As mentioned already when studying pointers to functions, callback functions are heavily used in Microsoft Windows programming. Besides the regular variables, these functions, called procedures, can take objects as argument. These functions are a little more restrictive.

A pointer to function is a type of function whose name can be assigned to a variable as if it were a regular variable. This eases their use in Win32 procedures and VCL's events. The syntax of declaring a pointer to function is:

DataType (*FunctionName)(ObjectName);

The DataType is the kind of value the function will return.

The FunctionName must be a valid name for a function. Because you are creating a pointer to function, the name of the function must be followed by an asterisk.

This time, unlike pointer to functions of void or other regular data types, a pointer to function that involves an object type must necessarily have at least one argument of class or structure type.

To illustrate this use of pointers to function, we will take an example:

On a Cartesian coordinate system, a line is known as a junction of two points. One of the operations you can perform on such a line is to calculate its length. The equation used is:

To calculate this distance, you can declare a function that would take two points as arguments. This function can be implemented and tested as follows:

//---------------------------------------------------------------------------

#include <iostream>

#include <math.h>



using namespace std;





//---------------------------------------------------------------------------





namespace Geometry

{

struct TPoint

{

    double x;

    double y;

    TPoint(double X=0, double Y=0) : x(X), y(Y) {}

};

}

//---------------------------------------------------------------------------

double Distance(Geometry::Point Pt1, Geometry::Point Pt2)

{

    double L1 = pow(Pt2.x - Pt1.x, 2);

    double L2 = pow(Pt2.y - Pt1.y, 2);

    return sqrt(L1 + L2);

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    Geometry::Point P(-3, 2);

    Geometry::Point Q(4, -1);

    double Length = Distance(P, Q);



    cout << "The distance between P(-3, 2) and Q(4, -1) is " << Length;



    

    

    return 0;

}

//---------------------------------------------------------------------------

On a Cartesian coordinate system, a triangle is represented by three points:

Because this definition does not distinguish a particular type of triangle, it allows calculating the perimeter of a triangle, which is simply done by adding the lengths of the three sides. To perform this calculation, you can create a function that takes three points as arguments. Because a function that performs the distance calculation is already available, you can pass three of its pointers to the new function. Each argument is passed as a pointer to a function that takes two Point objects. After specifying the arguments, pass the necessary arguments that will actually be passed to the function that performs the distance calculations. Such a function can be declared as follows:

double Perimeter(double (*Length1)(Point A, Point B),

                 		 double (*Length2)(Point B, Point C),

                      	 double (*Length3)(Point A, Point C),

                      	 Point First, Point Second, Point Third);

To implement this function, you must call the Distance function for each argument passed as pointer to function. Other than than, you would follow the same rules for implementing functions. Our Perimeter() function can be implemented as follows:

//---------------------------------------------------------------------------

double Perimeter(

                      double (*Length1)(Point A, Point B),

                      double (*Length2)(Point B, Point C),

                      double (*Length3)(Point A, Point C),

                      Point First, Point Second, Point Third )

{

    double AB = (*Length1)(First, Second);

    double BC = (*Length2)(Second, Third);

    double AC = (*Length3)(First, Third);

    return AB + BC + AC;

}

//---------------------------------------------------------------------------

So far, the compiler does not know how the calculations are performed for the calls in the Perimeter() function. You let the compiler know this when calling the Perimeter() function. In this case, you provide the name of each function that performs the needed calculation. For our example, the name of the function is Distance. Therefore, you would pass it three times. In the function call, the name of the function is used because the actual argument is a pointer to function. The Perimeter() function can be tested as follows:

//---------------------------------------------------------------------------

#include <iostream>

#include <math.h>



using namespace std;





//---------------------------------------------------------------------------





namespace Geometry

{

struct TPoint

{

    double x;

    double y;

    TPoint(double X=0, double Y=0) : x(X), y(Y) {}

};

}

//---------------------------------------------------------------------------

double Distance(Geometry::Point Pt1, Geometry::Point Pt2)

{

    double L1 = pow(Pt2.x - Pt1.x, 2);

    double L2 = pow(Pt2.y - Pt1.y, 2);

    return sqrt(L1 + L2);

}

//---------------------------------------------------------------------------

using namespace Geometry;

double Perimeter(

                      double (*Length1)(Point A, Point B),

                      double (*Length2)(Point B, Point C),

                      double (*Length3)(Point A, Point C),

                      Point First, Point Second, Point Third )

{

    double AB = (*Length1)(First, Second);

    double BC = (*Length2)(Second, Third);

    double AC = (*Length3)(First, Third);

    return AB + BC + AC;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    Geometry::Point Pt1(-3, -2);

    Geometry::Point Pt2(2, -2);

    Geometry::Point Pt3(4, 2);



    double Perim = Perimeter(Distance, Distance, Distance, Pt1, Pt2, Pt3);



    cout << "Perimeter: " << Perim << endl;



    

    

    return 0;

}

//---------------------------------------------------------------------------

This would produce:

Perimeter: 17.5344



Press any key to continue...

To simplify the declaration of the function that takes an argument as pointer to function, you can type define the argument using the typedef keyword. This can be done as follows:

//---------------------------------------------------------------------------

#include <iostream>

#include <math.h>



using namespace std;





//---------------------------------------------------------------------------





namespace Geometry

{

struct TPoint

{

    double x;

    double y;

    TPoint(double X=0, double Y=0) : x(X), y(Y) {}

};

}

//---------------------------------------------------------------------------

double Distance(Geometry::Point Pt1, Geometry::Point Pt2)

{

    double L1 = pow(Pt2.x - Pt1.x, 2);

    double L2 = pow(Pt2.y - Pt1.y, 2);

    return sqrt(L1 + L2);

}

//---------------------------------------------------------------------------

typedef double (*SideLength)(Geometry::Point First,

                                        Geometry::Point Second);

double Perimeter(SideLength, SideLength, SideLength,

                            Geometry::Point First, Geometry::Point Second,

                            Geometry::Point Third );

//---------------------------------------------------------------------------

using namespace Geometry;



int main(int argc, char* argv[])

{

    Point Pt1(-3, -2);

    Point Pt2( 2, -2);

    Point Pt3( 4,  2);



    double Perim = Perimeter(Distance, Distance, Distance, Pt1, Pt2, Pt3);



    cout << "Perimeter: " << Perim << endl;



    

    

    return 0;

}

//---------------------------------------------------------------------------

double Perimeter(

                      double (*Length1)(Point A, Point B),

                      double (*Length2)(Point B, Point C),

                      double (*Length3)(Point A, Point C),

                      Point First, Point Second, Point Third )

{

    double AB = (*Length1)(First, Second);

    double BC = (*Length2)(Second, Third);

    double AC = (*Length3)(First, Third);

    return AB + BC + AC;

}

//---------------------------------------------------------------------------

In this program, SideLength is another name for a pointer to function that takes two Point as arguments.

Based on this approach, you can also calculate the Perimeter of a rectangle or any quadratic or other geometric figure whose corners can be identified on a Cartesian coordinate system:

Classes and Self-Return

 

Self Returning an Object

The constructors are not the only member functions that can be declared with the name of the class. C++ allows you to manipulate the members of a class without using an external function. This technique uses a member function that can return the parent class. To have a function that can refer to the object itself, in the body of the class, declare a method that holds the same name as the class, followed by a valid name of a function and the parentheses. Here is an example:

//---------------------------------------------------------------------------

#ifndef FlatShapesH

#define FlatShapesH

//---------------------------------------------------------------------------

namespace FlatShapes

{

struct TTriangle

{

private:

    double TriBase;

    double TriHeight;

    double getBase() const;

    void   setBase(const double B);

    double getHeight() const;

    void   setHeight(const double H);

public:

    void   setDimensions(const double B, const double H);

    TTriangle();

    TTriangle(double B, double H);

    TTriangle(const TTriangle &Tri);

    ~TTriangle();

    double Area() const { return TriBase * TriHeight / 2; }



    TTriangle Additional();



    __property double Base = { read = getBase, write = setBase };

    __property double Height = { read = getHeight, write = setHeight };

};

}

//---------------------------------------------------------------------------

#endif

An example of using such a function would consist of changing the value of each member of the class. Since the function is declared as returning the value of the same variable, you can implement it as follows:

//---------------------------------------------------------------------------







#include "FlatShapes.h"

//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

namespace FlatShapes

{

TTriangle::TTriangle()

    : TriBase(0.00), TriHeight(0.00)

{

}

//---------------------------------------------------------------------------

TTriangle::TTriangle(double B, double H)

    : TriBase(B), TriHeight(H)

{

}

//---------------------------------------------------------------------------

TTriangle::TTriangle(const TTriangle &Tri)

    : TriBase(Tri.TriBase), TriHeight(Tri.TriHeight)

{

}

//---------------------------------------------------------------------------

TTriangle::~TTriangle()

{

}

//---------------------------------------------------------------------------

double TTriangle::getBase() const

{

    return (TriBase < 0 ) ? 0 : TriBase;

}

//---------------------------------------------------------------------------

void   TTriangle::setBase(double B)

{

    TriBase = ( B < 0 ) ? 0 : B;

}

//---------------------------------------------------------------------------

double TTriangle::getHeight() const

{

    return (TriHeight < 0) ? 0 : TriHeight;

}

//---------------------------------------------------------------------------

void   TTriangle::setHeight(double H)

{

    TriHeight = (H < 0 ) ? 0 : H;

}

//---------------------------------------------------------------------------

void   TTriangle::setDimensions(const double B, const double H)

{

    setBase(B);

    setHeight(H);

}

//---------------------------------------------------------------------------

TTriangle TTriangle::Additional()

{

    TTriangle Tri;



    // The constant double values used here were randomly chosen

    Tri.TriBase   = TriBase + 12.52;

    Tri.TriHeight = TriHeight + 8.95;



    return Tri;

}

//---------------------------------------------------------------------------

}

Calling this self-returning function is equivalent to changing the values of the member variables, as illustrated when called in the main() function:

//---------------------------------------------------------------------------

#include <iostream>



 

#include "FlatShapes.h"



//---------------------------------------------------------------------------

using namespace std;

using namespace FlatShapes;



void ShowCharacteristics(const TTriangle*);

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TTriangle Angular;



    Angular.setDimensions(22.44, 26.38);

    ShowCharacteristics(&Angular);



    cout << endl << endl;

    TTriangle Plane = Angular.Additional();

    ShowCharacteristics(&Plane);



    

    

    return 0;

}

//---------------------------------------------------------------------------

void ShowCharacteristics(const TTriangle* Tri)

{

    cout << " - Triangle Characteristics -";

    cout << "\nBase:   " << Tri->Base;

    cout << "\nHeight: " << Tri->Height;

    cout << "\nArea:   " << Tri->Area();

}

//---------------------------------------------------------------------------

You can use this ability to declare almost any type of function that returns the same class. One particular method can be used to modify the default values of the member variables. Another method can be used to convert the values of another class into those needed by the class.

The this Pointer

C++ proposes an alternative to returning an object from one of its member functions. Instead of explicitly declaring a variable when implementing a function that returns the same object, 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 Additional() method of the TTriangle object above so it would return the same variable that calls it. Because the method will return the same object, you do not need to declare a local variable to hold the changed variable. Since the member variables of the object will be modified, the member function 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. Here is the new implementation of the function:

//---------------------------------------------------------------------------

TTriangle TTriangle::Additional()

{

    // The constant double values used here were randomly chosen

    Tri.TriBase   = TriBase + 12.52;

    Tri.TriHeight = TriHeight + 8.95;



    return *this;

}

//---------------------------------------------------------------------------

Using the same approach, you can define and use other methods that return the same object:

//---------------------------------------------------------------------------

#ifndef FlatShapesH

#define FlatShapesH

//---------------------------------------------------------------------------

namespace FlatShapes

{

struct TTriangle

{

private:

    double TriBase;

    double TriHeight;

    double getBase() const;

    void   setBase(const double B);

    double getHeight() const;

    void   setHeight(const double H);

public:

    void   setDimensions(const double B, const double H);

    TTriangle();

    TTriangle(double B, double H);

    TTriangle(const TTriangle &Tri);

    ~TTriangle();

    double Area() const { return TriBase * TriHeight / 2; }



    TTriangle Additional();

    TTriangle AddAConstant(const double d);

    TTriangle AddAnotherObject(const TTriangle& E);



    __property double Base = { read = getBase, write = setBase };

    __property double Height = { read = getHeight, write = setHeight };

};

}

//---------------------------------------------------------------------------

#endif

Such methods can be implemented to return the this pointer and the same object that made the call:

//---------------------------------------------------------------------------







#include "FlatShapes.h"

//---------------------------------------------------------------------------



//---------------------------------------------------------------------------

namespace FlatShapes

{

. . . No Change

//---------------------------------------------------------------------------

TTriangle TTriangle::Additional()

{

    // The constant double values used here were randomly chosen

    TriBase   = TriBase + 12.52;

    TriHeight = TriHeight + 8.95;



    return *this;

}



//---------------------------------------------------------------------------

TTriangle TTriangle::AddAConstant(const double d)

{

    TriBase   = TriBase + d;

    TriHeight = TriHeight + d;



    return *this;

}

//---------------------------------------------------------------------------

TTriangle TTriangle::AddAnotherObject(const TTriangle& E)

{

    TriBase   += E.TriBase;

    TriHeight += E.TriHeight;



    return *this;

}

//---------------------------------------------------------------------------

}

Since the function that returns the this pointer returns it as a pointer, you can reinforce the fact that the variable that is being returned is modified. Therefore, instead of returning the object as a regular variable, you should make the returned value a reference:

//---------------------------------------------------------------------------

#ifndef FlatShapesH

#define FlatShapesH

//---------------------------------------------------------------------------

namespace FlatShapes

{

struct TTriangle

{

private:

    double TriBase;

    double TriHeight;

    double getBase() const;

    void   setBase(const double B);

    double getHeight() const;

    void   setHeight(const double H);

public:

    void   setDimensions(const double B, const double H);

    TTriangle();

    TTriangle(double B, double H);

    TTriangle(const TTriangle &Tri);

    ~TTriangle();

    double Area() const { return TriBase * TriHeight / 2; }

    TTriangle& Additional();
    TTriangle& AddAConstant(const double d);
    TTriangle& AddAnotherObject(const TTriangle& E);

    __property double Base = { read = getBase, write = setBase };
    __property double Height = { read = getHeight, write = setHeight };

    };
}
//---------------------------------------------------------------------------
#endif

In this case, remember to use the reference operator, the ampersand:

//---------------------------------------------------------------------------
TTriangle& TTriangle::Additional()
{
    // The constant double values used here were randomly chosen
    TriBase   = TriBase + 12.52;
    TriHeight = TriHeight + 8.95;

    return *this;
}
//---------------------------------------------------------------------------
TTriangle& TTriangle::AddAConstant(const double d)

{
	TriBase   = TriBase + d;
	TriHeight = TriHeight + d;

	return *this;
}
//---------------------------------------------------------------------------
TTriangle& TTriangle::AddAnotherObject(const TTriangle& E)
{
	TriBase   += E.TriBase;
	TriHeight += E.TriHeight;

	return *this;
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Ending the Lesson

  • Close your programming environment

Previous Copyright © 2001-2026, FunctionX Monday 25 December 2023 Next