Inheritance in C++

You must finish reading this post before this post.

The class is not enough to support object-oriented programming and design. To disparate classes from another, we have nested classes. But, it is a partial solution to fully relate one class to another. 

When we have multiple classes for the same feature, memory grows. In the mean time, access time slows. 

                          Growing Memory ∝ Slowing the access time

We need hierarchies of classes but with added features. C++ has a mechanism to create a hierarchy. The process of creating a derived class is called Inheritance.

When Class 2 wants to access the features of Class 1, Class 2 is inherited from class 1. This is called Inheritance. If the class is inherited, we can access its protected members but not the private members of it. 




Programs are drawn into model to solve the problems. There are so objects in the world and they all have relationships. One class can have another as a member variable. The relationships are: 

  • has - a
  • inclusion  

class Subjects {
       Module CloudComputing;
       Module physics;
       Module BigData;
};

Class Subjects 'has-a' module (More than one) 

These terms are really important in modelling the real world applications.

  • has-a
  • is-an instance of  (Eg: Shirley is a girl, Cloudcomputing is an instance of Subjects, etc.,) 
  • is-a kind of  (Eg: Girls are Humans)

'is-an instance of' is mostly related to objects. 'is-a kind of' is related to sub-class. 

'is-a kind' of another way to take advantage of redundancy.  Because the properties of the Subjects will be reflected to each Module as well. In other words, Sunflower and rose will derive most of the features from flower. This new concept is called - Inheritance. 

If any of the properties of flower changes, it will be reflected in other sub classes like sunflower and rose. It is a way of encoding the 'is-a-kind-of' relationship. 

Subjects is a base or super class and also called as generalised class. Module is a sub-class or derived class and also called as specialised class.

In java, we write this as 

class Subjects extends Module { }

  • As module inherits the Subjects, it can do anything that Subjects can do. 

Will add few details ***************************

  • All the fields and methods of Subjects are transparently included in Module. 

Will add few details ******************

  • Derived class can add new data or functions 
  • Derived class can override(overrule) base class behavior

Rules of Inheritance

  • All data and methods in the base(super) class are automatically inherited by derived (sub) class.

It will be inherited by the immediate super class.

  • Changes in base class can also be automatically propagated into derived class. 
  • If a method exists in both the classes, derived class overrides. Overriding can only be done for functions, and not for data members. 
  1. If same method exists in both classes, derived/child class takes precedence. Alternatively, more specialised version takes higher priority. 
  2. If a method doesn't exist in the derived class, then go to base class and check if the function exists. If not exists in the immediate base class, keep going higher in the hierarchy. 
  • Derived class inherits the functions, but not the variables.

class Subjects {
    learnToCode() {"Subjects : Learn to Code"};
    sitForExam() {"Subjects : Sit for Exam"};
};

class Physics : public Subjects {
    sitForExam() 
    {
     this->learnToCode(); 
     std::cout << "Physics: Sit for Exam" << std::endl;
    };
    learnRProgram() {"Physics : Learn R Programming"};   
};

class BigData : public Physics {
    learnToCode() {"BigData : Learn to Code"};
    learnRProgram() {"BigData : Learn R Programming"};
};

class CloudComputing : public Subjects {
    learnToCode() {"CloudComputing : Learn to Code"};
    sitForExam() {"CloudComputing : Sit for Exam"};
};

Physics pilot;
BigData Ben;
CloudComputing Clara;

Ben.sitForExam();       /* Physics: Sit for Exam */
Clara.learnToCode();    /* CloudComputing : Learn to Code */
pilot.sitForExam();     /* Physics: Sit for Exam */
Ben.learnToCode();      /* BigData : Learn to Code */
Clara.learnRProgram();  /* Doesn't compile */
pilot.learnRProgram();  /* Physics : Learn R Programming */

Points for takeaways

  1. In the derived class, parent class method can be called. 
  2. We can't recapture the base class from outside by using other derived object. Any access to the base class member must be mediated by the public part of the derived class object.
  3. Derived class constructor 
  4. Can access the parent class member(learnToCode) from the derived class using this. 

exclass (int x, int y, int z) : exbase (x, y);

Invoking Overridden Methods

If I really want to call Army's Print method, then reuse the code. 

Use the scope resolution operator to explicitly call an overriden method from the derived class as shown in Method 2 of the below program. 

This method 2 will be used as long as the Army is the parent of the ArmyHospital.

#include <iostream>
using namespace std;

class Army                         // Class declaration
{
public:
    Army() : armyName_("Shirley") {}
     string getName() {
        return armyName_;
    }
    //virtual.     >>> Turn it on and off and see the difference
    void print() {
        cout << getName() << endl;
    }
private:
    string armyName_;
};

class ArmyHospital : public Army 
{
public:
    ArmyHospital() : hospitalName_("LEH Hospital") {}
    string getHospitalName() {
        return hospitalName_;
    }
    void print() {
        // Method 1:
        //cout << getName() << endl;
        // Method 2:
        Army::print();
        cout << getHospitalName() << endl;
    }
private: 
    string hospitalName_;

};


int main() 
{

    Army* off = new Army;
    ArmyHospital* hos = new ArmyHospital;
    
    cout << "Army pointer ";
    off->print();
    cout << endl << endl;
    
    cout << "ArmyHospital pointer ";
    hos->print();
    cout << endl << endl;
  
    Army* major = new ArmyHospital;
    cout << "Major pointer ";
    major->print();
    cout << endl << endl;
  
    return 0;
}


Output:

1
2
3
4
5
6
7
8
9
10
Army pointer Shirley


ArmyHospital pointer Shirley
LEH Hospital


Major pointer Shirley

Click here to debug the above program.

Constructor of the base class is called first before the constructor of the derived class executes using the initialiser list in the derived class constructor. 

ArmyHospital() : hospitalName_("LEH Hospital") {}

When this particular line is hit,  default Army() constructor is executed first and then ArmyHospital() is executed as there is no explicit initialisation of Army constructor.


References

https://stackoverflow.com/questions/2391679/why-do-we-need-virtual-functions-in-c

https://stackoverflow.com/questions/2436125/c-access-derived-class-member-from-base-class-pointer

oreilly.com/radar/where-programming-ops-ai-and-the-cloud-are-headed-in-2021/

https://www.enjoyalgorithms.com/blog/why-should-we-learn-oops-concepts-in-programming

https://www.learncpp.com/cpp-tutorial/adding-new-functionality-to-a-derived-class/

https://www.doc.ic.ac.uk/lab/cplus/c%2B%2B.rules/chap7.html

https://mariusbancila.ro/blog/2021/11/16/virtual-inheritance-in-c/

Comments