Hierarchical inheritance is a type of inheritance in C++ where multiple classes inherit from the same base class. It allows related classes to share common functionality while maintaining their own unique features.
- A single base class can be inherited by multiple derived classes.
- Reduces code duplication by sharing common members across related classes.
Real-World Example: A Vehicle class can be used as a base class, while Car, Bus, and Bike are derived classes. All of them inherit common vehicle properties but can have their own unique features.

The above diagram shows hierarchical inheritance, where multiple derived classes (B and C) inherit from a single base class (A).

The hierarchy can be extended further by deriving additional classes from existing derived classes, forming a tree-like inheritance structure. Here, X and Y inherit from B, while M and N inherit from C.
Syntax
In hierarchical inheritance, multiple classes inherit from the same base class.
class Base {
// Base class members
};
class Derived1 : public Base {
// Derived1 members
};
class Derived2 : public Base {
// Derived2 members
};
Where:
- Base is the parent class.
- Derived1 and Derived2 inherit from Base.
- Each derived class gets its own copy of the accessible members of the base class.
Working of Hierarchical Inheritance
In hierarchical inheritance, a single base class serves as the parent for multiple derived classes. Each derived class inherits the accessible members of the base class and can also define its own additional data members and member functions.
- Multiple derived classes inherit from a common base class.
- Each derived class can access the inherited members according to the inheritance access specifier.
- Derived classes can add their own data members and member functions.
- Changes in the base class are automatically available to all derived classes.
Example: Multiple Derived Classes Sharing a Base Class
#include<iostream>
using namespace std;
class A //superclass A
{
public:
void show_A() {
cout<<"class A"<<endl;
}
};
class B : public A //subclass B
{
public:
void show_B() {
cout<<"class B"<<endl;
}
};
class C : public A //subclass C
{
public:
void show_C() {
cout<<"class C"<<endl;
}
};
int main() {
B b; // b is object of class B
cout<<"calling from B: "<<endl;
b.show_B();
b.show_A();
C c; // c is object of class C
cout<<"calling from C: "<<endl;
c.show_C();
c.show_A();
return 0;
}
Output
calling from B: class B class A calling from C: class C class A
Explanation: Both B and C inherit from class A. Therefore, objects of both derived classes can access the inherited member function show_A() along with their own member functions.
Constructor and Destructor Behavior
In hierarchical inheritance, constructors and destructors execute in a specific order whenever a derived class object is created or destroyed.
Constructor Order
When an object of a derived class is created:
- The base class constructor is called automatically before the derived class constructor.
- This ensures that all inherited members are properly initialized before the derived class starts executing.
- The initialization process always proceeds from the base class to the derived class.
Destructor Order
When the object goes out of scope or is destroyed:
- The derived class destructor executes first.
- After the derived class cleanup is complete, the base class destructor is called.
- This reverse order ensures that resources owned by the derived class are released before inherited resources are cleaned up.
Example: Constructor Invocation in Hierarchical Inheritance
#include <iostream>
using namespace std;
// Base class
class shape {
public:
string name;
int sides;
shape(string name, int sides) // constructor
{
this->name = name; // this pointer
this->sides = sides;
}
};
// Derived class
class triangle : public shape // mode is public
{
private:
int base;
int height;
public:
// shape constructor taking arguments
// from triangle constructor
triangle(string name, int sides, int base, int height) : shape(name, sides)
{
this->base = base;
this->height = height;
}
void area()
{
cout << "area of triangle: "
<< (0.5 * base * height) << endl;
}
void details()
{
cout << "shape is: " << name << endl;
cout << "no. of sides are: " << sides << endl;
cout << "base is: " << base << endl;
cout << "height is: " << height << endl;
area(); // calling area()
}
};
// Derived class
class square : public shape {
private:
int height;
public:
// shape constructor taking arguments
// from square constructor
square(string name, int sides, int height) : shape(name, sides)
{
this->height = height;
}
void area()
{
cout << "area of square: " << (height * height)
<< endl;
}
void details()
{
cout << "shape is: " << name << endl;
cout << "no. of sides are: " << sides << endl;
cout << "height is: " << height << endl;
area(); // calling area()
}
};
int main()
{
// Creating objects
triangle t("triangle", 3, 2, 3);
square s("square", 4, 2);
t.details();
cout << endl << endl;
s.details();
return 0;
}
Output
shape is: triangle no. of sides are: 3 base is: 2 height is: 3 area of triangle: 3 shape is: square no. of sides are: 4 height is: 2 area of square: 4
Explanation: Both Triangle and Square inherit from Shape. Whenever a derived-class object is created, the Shape constructor executes before the constructor of the derived class.
Advantages of Hierarchical Inheritance
Hierarchical inheritance allows multiple derived classes to share common functionality from a single base class while maintaining their own unique features.
- Reduces code duplication by sharing common functionality and improves code reusability.
- Simplifies maintenance by centralizing common features.
- Models real-world hierarchical relationships effectively.
- Makes it easier to extend applications with additional derived classes.
Limitations of Hierarchical Inheritance
Although hierarchical inheritance promotes code reuse, it can increase complexity and maintenance effort in large class hierarchies.
- Changes in the base class may impact all derived classes that depend on it.
- Strong dependency between classes can reduce flexibility and extensibility.
- Large inheritance hierarchies can become harder to understand, maintain, and debug.
- Poorly designed hierarchies may increase complexity and reduce code readability.