Basics of Inheritance in C++ With Examples

This article demonstrates some examples of inheritance.

Inheritance is an extremely useful and exciting object oriented programming feature. Inheritance allows you to organize and reuse code effectively. Think of inheritance from a general perspective. Take your example; you inherit several characteristics from your parents. If your parents are tall, it is more likely that you will be taller than a person whose parents are shorter. Yes, exceptions are always there, but it has been genetically proved that human being inherit certain characteristics of their ancestors.

Inheritance in programming is somewhat similar concept. Replace human beings with objects and you will understand what does that mean. In C++ we can define a parent child relationship between classes in such a way that child class will inherit all the attributes of its parent class plus it will have its own attributes and functions.

Inheritance is based on the principle of is-a relationship. A typical example of which is that a square ‘is a’ shape, a man ‘is a’ human, a pilot ‘is an’ employee and so on. Following are some extremely important concepts that need to be understood before exploring inheritance in C++ further.

What is a Parent/Base Class?

A parent class is a class which acts as a parent for the classes which inherit from it. As aforementioned, you inherit some attributes from you parents but in case of parent class, all the inheriting or child classes will inherit all the attributes of the parent class and you will not have to write that piece of code again. Inheritance fosters reusability and code is more organized. Parent class is also called base class

What is a Child/Derived Class?

Child class is a class that inherits base class. In child class you have access to all the attributes and functions defined in the base class. One parent class can have as many child classes as it want. Child class is often known as the derived class.

We will explain the above mentioned concept with simplest possible example. We will have a class A which will be the parent class and two child classes B and C. Have a look at

Example 1

Code:

#include <iostream>
#include <string>
using namespace std;

class A
{
public:
void parentfunction()
{
cout <<"This is parent class function";
}
};

class B: public A
{
public:
void childfunction()
{
cout <<"\nThis is Child B\n";
}
};

class C: public A
{
public:
void childfunction()
{
cout <<"\nThis is Child C";
}
};


int main()
{
B b;
C c;
b.parentfunction();
b.childfunction();
c.parentfunction();
c.childfunction();
}

In Example 1, we have defined a parent class A and two of its child classes B and C. Pay particular attention on syntax of inheritance.

If we have two class; a parent class A and a child class B and we want B to inherit from A, we use a colon as between B and A with B on the left side of colon.

Code:

B: public A

This means that class B is inheriting class A publicly and is able to access all the members and functions of class A.

In Example 1, we have defined a function named parentfunction() inside the parent class A. In the child classes B and C we have defined one function each, named childfunction().

In the main function we have defined an object b of class B and object c of class c. Note, here we do not have defined any object of the parent class A but yet we will be able to access its function parentfunction() through the base classes. We have first called parentfunction() from object b although class B doesn’t have it. Still we are able to call it because B is inheriting A. In the same way we called parentfunction() from the other child C. The output of this code is

Output 1

Output1

Now we have basic understanding of how inheritance basically works. We can move to more realistic example.

Consider the example of a shape. A shape itself is nothing. Shapes exist in the form of square, a circle, rectangle, polygons etc. Alternatively, we can say that a square is a shape, a circle is also a shape and rectangle is also a shape. This shape example is probably the best example to explain inheritance in real life C++ objects and we will also further explain inheritance through this example. Consider Example 2. Read the code carefully and try to comprehend what is happening here, the explanation of the code is given after that.

Example 2

Code:

#include <iostream>
#include <string>
using namespace std;
class Shape
{
public:
stri#include <iostream>
#include <string>
using namespace std;

class Shape
{
public:
string name;
int angles;

string getname()
{
return name;
}

int getangles()
{
return angles;
}
};

class Square: public Shape
{
public:
int length, width;

int getarea()
{
return length * width;
}
};

class Circle: public Shape
{
public:
int radius;
double getarea()
{
return 3.14 * radius * radius;
}
};



int main()
{
Square S;
Circle C;

S.name = "Square";
S.length = 4;
S.width = 6;
S.angles = 4;

C.name = "Circle";
C.angles = 0;

C.radius= 3;

cout <<"Then name of shape S is:"<<S.getname();
cout <<"\nShape S has: "<<S.getangles()<<" angles";
cout <<"\nThe length of square is: "<<S.length;
cout <<"\nThe width of square is: "<<S.width;
cout <<"\nThe area of square is: "<<S.getarea();

cout<<"\n\n*****************************";

cout <<"\n\nThen name of shape C is:"<<C.getname();
cout <<"\nShape C has: "<<C.getangles()<<" angles";
cout <<"\nThe radius of circle is: "<<C.radius;
cout <<"\nThe area of circle is: "<<C.getarea();
}

In Example 2, we have a parent class shape. The class has two members name and angles. All the shapes have some name and angle. As a rule of thumb, all those variables and methods that are common in all the child classes should be packaged in the parent class. Here every shape has a name and angle so we have written name and angle in the parent class. Also, we want to get shape name and angle. We can do so by writing getname() and getangle() function as we have done in parent class. Child classes should only contain those members and functions which are unique to the child.

Here we have two child classes; a Square class and a Circle class. A square has length and width but circle doesn’t have length and width, therefore we haven’t added length and width variables in parent class, Shape; instead we have added it in the child class, Square. Similarly if we look at circle, it has radius but a square doesn’t have any radius, therefore we have added radius as a member in Circle class not in parent class Shape.

In the main class we have assigned values to both name and angle of Square and Circle. We have assigned values to length and width for the Square object S and radius for Circle object C. Note we have also defined getarea() method for both Circle and Square. You must be thinking if getarea() method is common for both circle and square, why haven’t we packaged it in the parent class. The reason is that formula for calculation of areas of square and circle is different. However base classes with same function names lies in the heart of another advanced object oriented concept, polymorphism which we will see in some of our other tutorials.
Next we have displayed names and angles for child classes square and circle, the length and width of square, the radius of circle and the areas of both square and circle. The output of Example 2 is as follows:

Output 2

Output2

Function Overriding

A question arises here what if the parent class and the child class has same function name. Which one will be executed? For example if parent class has a function named display(). Similarly a child class also contain function named display(). Which function will be called, the child class or the base class? The answer is that if a child class has function name similar to a function in parent class with same signature, return type and parameters, child class function will be executed. This phenomenon is known as operator overloading.

We can modify Example 1 slightly to explain function overriding. See Example 3.

Example 3

Code:

#include <iostream>
#include <string>
using namespace std;

class A
{
public:
void Display()
{
cout <<"This is parent class function";
}
};

class B: public A
{
public:
void Display()
{
cout <<"\nThis is Child B\n";
}
};

class C: public A
{
public:
void Display()
{
cout <<"\nThis is Child C";
}
};

int main()
{
A a;
B b;
C c;
a.Display();
b.Display();
c.Display();
}

In Example 3, we have Display function in parent as well as both the child classes. When Display() function is called from the object of the parent class, the parent class Display function will be called. But when Display() function is called from the objects of the child classes, although they are inheriting the parent class, they derived class display function will be called. The output of the code in Example 3 is as follows

Output 3

Output3

Abstract Class

Abstract class is a class which cannot be instantiated. Object of abstract class cannot be created. The class which implements the abstract class has to implement all the pure virtual functions of the abstract class. Consider Example 2 again; we mentioned that shape itself is nothing. Real objects are of the base classes like Square and Circle. However every shape has an area, therefore getarea() function can be implemented as pure virtual function.

Virtual Functions

Virtual functions are those functions that are declared in the base class with intent to be overridden by the derived classes, however deriving classes have options whether to override it or not. A virtual function is declared with the keyword virtual and usually do not contain any definition. The classes that derive the base class provide the definition for the virtual function.

Code:

virtual int getarea()
{
 return 0;
};


Pure Virtual Function

In case of virtual function, deriving class has the option to override the virtual function or not but in case of pure virtual function base class, the deriving class must implement the function inside its body. A pure virtual has no body and have a very simple declaration. Inside the body of the base class you just have to write a pure function and assign a value 0 to it as in the following line of code.

Code:

virtual int getarea() = 0;

An abstract class must contain at least one pure virtual function. In Example2, we can define getarea() function as pure virtual now whichever class derives the shape class it will have to implement the definition of getarea() function. Modify Example 2 as follows:

Example 4

Code:

#include <iostream>
#include <string>
using namespace std;

class Shape
{
public:
string name;
int angles;

string getname()
{
return name;
}

int getangles()
{
return angles;
}

virtual float getarea() = 0; // Pure Virtual Function

};

class Square: public Shape
{
public:
int length, width;

float getarea()
{
return length * width;
}
};

class Circle: public Shape
{
public:
int radius;

float getarea()
{
return 3.14 * radius * radius;
}

};

int main()
{
Square S;
Circle C;

S.name = "Square";
S.length = 4;
S.width = 6;
S.angles = 4;

C.name = "Circle";
C.angles = 0;

C.radius= 3;

cout <<"Then name of shape S is:"<<S.getname();
cout <<"\nShape S has: "<<S.getangles()<<" angles";
cout <<"\nThe length of square is: "<<S.length;
cout <<"\nThe width of square is: "<<S.width;
cout <<"\nThe area of square is: "<<S.getarea();

cout<<"\n\n*****************************";

cout <<"\n\nThen name of shape C is:"<<C.getname();
cout <<"\nShape C has: "<<C.getangles()<<" angles";
cout <<"\nThe radius of circle is: "<<C.radius;
cout <<"\nThe area of circle is: "<<C.getarea();

}

The output of Example 2 and Example 4 will be same but in case of Example 4, Shape Class is abstract because it contains one pure virtual method named getarea(). Therefore the derived classes Square and Circle will have to implement the getarea() function inside their bodies. Also, In Example 4, we cannot create object of Shape class.

On the other hand we saw that in case of Example 2, it was our choice whether to implement the getarea() function or not because it was not declared virtual in the parent class. Also, since in Example 2, Shape class was not abstract, we could directly create its object. The output of Example 4 will be as follows.

Output 4

Output4

Last modified: Tuesday, August 31, 2021, 11:48 AM