Home

Accessing a Member of a Parent From a Derived Class

 

Introduction

After deriving a class from another one, we have seen how you can "re-write" a property or method of the parent in the child class. When using a property or method in a child class, by default, if you call a property or method that is available in both the child and the parent class, the compiler would directly access the version in the child class. Consider the following example:

using namespace System;

public ref class CSquare
{
public:
    virtual String ^ Description();
    virtual void Display();
};

String ^ CSquare::Description()
{
    return L"A Square is a geometric shape with 4 equal sides";
}

void CSquare::Display()
{
    Console::WriteLine(L"Geomtric Shapes");
    Console::WriteLine(L"Name:       Square");
    Console::WriteLine(L"Description {0}", Description());
}

public ref class CCube : public CSquare
{
public:
    virtual String ^ Description() override;
    virtual void Display() override;
};

String ^ CCube::Description()
{
    return L"A cube is 3-dimensional box with 6 squares";
}

void CCube::Display()
{
    Console::WriteLine(L"Geomtric Shapes");
    Console::WriteLine(L"Name:       Cube");
    Console::WriteLine(L"Description {0}", Description());
}

int main()
{
    CCube ^ cube = gcnew CCube;

    cube->Display();

    Console::WriteLine();
    return 0;
}

This would produce:

Geomtric Shapes
Name:        Cube
Description: A cube is 3-dimensional box with 6 squares

Press any key to continue . . .

In the result of this program, the application defines a cube and includes the word square without defining what a square is. Based on the rules of overridden members that we have seen so far, you cannot directly access the Description() method of the CSquare class from a method of the CCube class. The solution is to "qualify" the parent method when calling it. This qualification is performed using the scope resolution operator :: by accessing the method in the parent class as if it were a static method. This can be done as follows:

void CCube::Display()
{
    Console::WriteLine(L"Geometric Shapes");
    Console::WriteLine(L"Name:       Cube");
    Console::WriteLine(L"Description {0}", CSquare::Description());
    Console::WriteLine(L"            {0}", Description());
}

int main()
{
    CCube ^ cube = gcnew CCube;

    cube->Display();

    Console::WriteLine();
    return 0;
}

This would produce:

Geomtric Shapes
Name:       Cube
Description A Square is a geometric shape with 4 equal sides
            A cube is 3-dimensional box with 6 squares

Press any key to continue . . .

In the same way, from the child class, you can access the members of the parent class by qualifying them but calling them as you would a static member.

Overloading a Method of a Parent Class

Consider the following virtual class:

Header File: Square.h
#pragma once

#include <string>
using namespace std;

class CSquare
{
protected:
    double _side;

public:
    CSquare(void);
    CSquare(double side);
    virtual ~CSquare(void);

    virtual string Description();
    virtual void Display();
	
    double getSide() const { return _side; }
    void setSide(const double sd) { _side = (sd <= 0) ? 0 : sd; }
	
    virtual double Area()
    {
	return _side * _side;
    }

    virtual double Perimeter()
    {
	return _side * 4;
    }
};
Source File: Square.cpp
#include <iostream>
#include <string>
#include "Square.h"
using namespace std;

CSquare::CSquare(void) : _side(0.00)
{
}

CSquare::CSquare(double side)
    : _side((side <= 0.00) ? 0.00 : side)
{
}

CSquare::~CSquare(void)
{
}

string CSquare::Description()
{
    return "A Square is a geometric shape with 4 equal sides";
}

void CSquare::Display()
{
    cout << "Geometric Shapes" << endl;
    cout << "Name:       Cube" << endl;
    cout << "Description " << Description() << endl;
    cout << "Side:       " << getSide() << endl;
    cout << "Perimeter:  " << Perimeter() << endl;
    cout << "Area:       " << Area() << endl;
}

This class can be tested as follows:

Source File: Exercise.cpp
#include <iostream>
#include <string>
#include "Square.h"
using namespace std;

int main()
{
    CSquare * care = new CSquare;

    care->setSide(24.85);
    care->Display();

    cout << endl;
    return 0;
}

This would produce:

Geometric Shapes
Name:       Cube
Description A square is a geometric shape with 4 equal sides
Side:       24.85
Perimeter:  99.4
Area:       617.5225

Press any key to continue . . .

Notice that, in the main() function, we called the Display() method of the CSquare class as we have been doing so far and we had to qualify the name of the method to clearly show what class it belongs to. In the same way, if you derive one class from another, when in the body of the derived class, if you want to access a member of the parent class, we saw that you could qualify the method.

In a derived class, if you want to re-implement a method of the parent class, instead of formally overriding it, you can overload it. The difference is, and you should be aware of it, that when overriding, you are redefining a method with the exact same signature (same name and same argument(s), if any). When overloading a method, remember that they different versions must have the same name but different argument(s). Based on this, if you overload a method in a child class, give it the same name but change something about the argument(s), either a different type of argument or a different number of arguments. Here is an example:

Header File: Cube.h
#pragma once
#include "square.h"

class CCube : public CSquare
{
public:
    CCube(void);
    ~CCube(void);

    virtual string Description(const int cube);
    virtual void Display();

    virtual double Area();
    virtual double Volume();
};

Notice that, the Description() method that is also available in the parent class without an argument, this time takes a constant integer. Also remember that you don't even have to use the argument; it is only used to distinguish it from the other one. When implementing the new version, you can do whatever you want with it and call it as you see fit.

Consider the following class:

Header File: Cube.h
#pragma once
#include "square.h"

class CCube : public CSquare
{
public:
    CCube(void);
    ~CCube(void);

    virtual string Description(const int cube);
    virtual void Display();

    virtual double Area(const int cube);
    virtual double Volume();
};
Source File: Cube.cpp
#include <iostream>
#include <string>
#include "Cube.h"
using namespace std;

CCube::CCube(void)
{
}

CCube::~CCube(void)
{
}

string CCube::Description(const int sqr)
{
    return "A cube is 3-dimensional box with 6 squares";
}

double CCube::Area(const int cube)
{
	return _side * 6;
}

double CCube::Volume()
{
	return _side * _side * _side;
}

void CCube::Display()
{
    cout << "Geomtric Shapes" << endl;
    cout << "Name:       Cube" << endl;
    cout << "Description " << Description(0) << endl;
    cout << "            " << Description() << endl;
    cout << "Side:       " << getSide() << endl;
    cout << "Side Area:  " << Area() << endl;
    cout << "Total Area: " << Area(0) << endl;
}
Source File. Exercise.cpp
#include "Cube.h"

int main()
{
    CCube * cube = new CCube;

    cube->setSide(24.85);
    cube->Display();

    return 0;
}

This program would not work because, in the CCube::Display() method, the compiler cannot locate the Description() method. When calling an overloaded method of a parent class from a derived class, in the derived class, as opposed to qualifying the name of the method as we learned in the previous section, you can create a synonym of of the method. To do this, in the body of the derived class, type the using keyword, followed by the name of the parent class, followed by the ::operator, followed by the name of the method that you had overridden. Here are two examples:

Header File: Cube.h
#pragma once
#include "square.h"

class CCube : public CSquare
{
public:
    CCube(void);
    ~CCube(void);

    virtual string Description(const int cube);
    virtual void Display();

    using CSquare::Description;
    using CSquare::Area;

    virtual double Area(const int cube);
    virtual double Volume();
};

This time, when calling the overridden method(s), the compiler would know which one you are referring to. The program would produce:

Geomtric Shapes
Name:       Cube
Description A cube is 3-dimensional box with 6 squares
            A Square is a geometric shape with 4 equal sides
Side:       24.85
Side Area:  617.523
Total Area: 149.1
Press any key to continue . . .
 

Previous Copyright © 2006 FunctionX, Inc. Next