Inheritance and Polymorphism in C++

Inheritance :

   Inheritance is one of the most important concepts of object-oriented programming. Inheritance allows to define a class based on another class. This facilitates greater ease in creating and maintaining an application.

   The class whose properties are inherited by another class is called the Base class. The class which inherits the properties is called the Derived class. For example, the Daughter class (derived) can be inherited from the Mother class (base).
   The derived class inherits all feature from the base class, and can have its own additional features.

To demonstrate inheritance, let's create a Mother class and a Daughter class:  

class Mother{
   public:
     Mother() {};
     void sayHi() {
        cout << "Hi";
     }
};
class Daughter {
   public:
     Daughter() {};
};

   The Mother class has a public method called sayHi()The next step is to inherit (derive) the Daughter class from the Mother class.

   This syntax derives the Daughter class from the Mother class:

class Daughter : public Mother{
   public:
     Daughter() {};
};

 
   The Base class is specified using a colon and an access specifier: public means, that all public members of the base class are public in the derived class. 

 In other words, all public members of the Mother class become public members of the Daughter class.

   As all public members of the Mother class become public members for the Daughter class, an object of type Daughter can be created and can call the sayHi() function of the Mother class for that object:

#include <bits/stdc++.h>
using namespace std;

class Mother{
   public:
     Mother() {};
     void sayHi() {
       cout << "Hi";
     }
};
class Daughter: public Mother{
   public:
     Daughter() {};
};
int main() {
   Daughter d;
   d.sayHi();
}   //Outputs "Hi"
  A derived class inherits all base class methods with the following exceptions:
  • Constructors and Destructors
  • Overloaded Operators
  • Friend Functions 

 Access Specifiers :

  Now, coming upto access specifiers in inheritance, public members may be accessed from anywhere outside of the class, while access to private members is limited to their class and friend functions. It's a good practice to use public methods to access private class variables.

  There is one more access specifier - protected. A protected member variable or function is very similar to a private member, with one difference - it can be accessed in the derived classes.

class Mother {
  public:
     void sayHi() {
       cout << var;
     }
  private:
     int var=0;
  protected:     int someVar;
};

Type of Inheritance :

  Access specifiers are also used to specify the type of inheritance. Remember, public is used to inherit the Daughter class. 

    class Daughter: public Mother  

   private and protected access specifiers can also be used here.

Public Inheritance : 

 public members of the base class become public members of the derived class and protected members of the base class become protected members of the derived class. A base class's private members are never accessible directly from a derived class, but can be accessed through calls to the public and protected members of the base class.

Protected Inheritance :

 public and protected members of the base class become protected members of the derived class.

Private Inheritance :

 public and protected members of the base class become private members of the derived class.

public inheritance is the most commonly used inheritance type. If no access specifier is used when inheriting classes, the type becomes private by default.

  When inheriting classes, the base class' constructor and destructor are not inherited. However, they are being called when an object of the derived class is created or deleted.
  To further explain this behavior, let's create a sample class that includes a constructor and a destructor:


class Mother {
   public:
     Mother(){
       cout <<"This is Mother Constructor"<<endl;
     }
     ~Mother(){
       cout <<"This is Mother Destructor"<<endl;
     }
};

Creating an object in main results in the following output:


int main() {
   Mother m;
}/* Outputs
  This is Mother Constructor

  This is Mother Destructor
  */


Inheritance :

Next, let's create a Daughter class, with its own constructor and destructor, and make it a derived class of the Mother :

class Daughter: public Mother {
  public:
   Daughter(){
     cout <<"This is Daughter Constructor"<<endl;
   }
   ~Daughter(){
     cout <<"This is Daughter Destructor"<<endl;
   }
};


Now, what happens when a Daughter object is created?


int main() {
Daughter m;
}
/*Outputs
This is Mother Constructor
This is Daughter Constructor
This is Daughter Destructor
This is Mother Destructor
*/


  Note that the base class' constructor is called first, and the derived class' constructor is called next. When the object is destroyed, the derived class' destructor is called, and then the base class' destructor is called.

The derived class needs its base class in order to work - that is why the base class is set up first.

Summary :

  Constructors : 

       The base class constructor is called first.

  Destructors :

       The derives class destructor is called first and then the base class destructor gets called.

The sequence of constructors and destructors makes it possible to specify initialization and de-initialzation scenarios for the derived class.

Comments