For working professionals
For fresh graduates
More
4. C++ Variable
10. C++ for Loop
12. C++ Lambda
13. Loop in C++
15. Array in C++
16. Strings in C++
17. Substring in C++
29. Vector in C++
30. Map in C++
31. Pair in C++
33. Iterators in C++
34. Queue in C++
36. Stack in C++
37. ifstream in C++
40. Templates in C++
43. Namespace in C++
46. Recursion in C++
48. C++ Shell
49. Setw in C++
51. Atoi in C++
54. C# vs C++
55. C++ GUI
56. C++ Game Code
57. Class in C++
58. C++ Header Files
63. Cin in C++
64. Printf in C++
65. Struct in C++
66. C++ List
68. C++ Comments
72. Sorting in C++
Hierarchical inheritance is a fundamental concept in object-oriented programming (OOP) where multiple classes inherit properties and behaviors from a single base class. We can think of it as a family tree, where the base class represents a grandparent, and various derived classes represent children and grandchildren, each inheriting traits from their ancestors.
Let us dive in and all about hierarchical inheritance in C++.
In order to learn what is hierarchical inheritance in C++, we must first discuss what single inheritance and multiple inheritance is. When multiple classes inherit from a common base class, we refer to it as hierarchical inheritance (i.e., Dog, Cat, and Horse all inheriting from Animal). Being able to build hierarchical class structures is extremely crucial as a C++ developer as we need it for many different programs.
Imagine a digital family tree where the grandparent class, Animal, represents the shared characteristics of all animals. From this root, various derived classes emerge: Dog, Cat, Horse, each inheriting traits like age, name, and the ability to eat(). However, each class also boasts unique qualities: Dog might bark(), Cat could meow(), and Horse might gallop().
Here are the advantages of hierarchical inheritance in C++:
Let us first learn the core concepts of hierarchical inheritance such as class hierarchy in C++ and the syntax.
At the heart of hierarchical inheritance in C++ lies the base class, also known as the parent or superclass. It serves as the blueprint for its descendants, holding common properties and behaviors that all derived classes will share. In our animal kingdom analogy, Animal would be the base class, defining shared traits like age, name, and the eat() function.
Derived classes, also known as child or subclasses, are the offspring of the base class. They inherit the attributes and methods of their parent while adding their unique characteristics. For example, Dog, Cat, and Horse are derived classes of Animal, each inheriting common traits but also having their own special abilities like barking, meowing, or galloping.
In C++, we establish this parent-child relationship using this syntax:
class DerivedClass : public BaseClass {
// Additional members specific to the DerivedClass
};
In the above code snippet:
The family tree analogy helps visualize the flow of inheritance and the relationships between classes. It also makes it easier to understand how hierarchical inheritance promotes code reusability and maintainability while modeling real-world scenarios. Imagine a family tree where each generation represents a class in our code:
Grandparents (Base Class)
|
Parents (Derived Class 1)
/ \
Child 1 (Derived Class 2) Child 2 (Derived Class 2)
How traits pass down:
In our C++ code, the analogy translates beautifully:
Example:
Shape (Base Class)
|
Polygon (Derived Class 1)
/ \
Triangle (Derived Class 2) Rectangle (Derived Class 2)
In the above example:
Let us lay the foundation for creating a rich and diverse animal kingdom within our C++ code with a simple structure.
Code:
#include <iostream>
#include <string>
using namespace std;
class Animal {
public:
int age;
string name;
Animal(int age, string name) : age(age), name(name) {} // Constructor to initialize
void eat() {
cout << name << " is eating." << endl;
}
};
class Dog : public Animal {
public:
Dog(int age, string name) : Animal(age, name) {} // Call base class constructor
void bark() {
cout << name << " is barking." << endl;
}
};
class Cat : public Animal {
public:
Cat(int age, string name) : Animal(age, name) {} // Call base class constructor
void meow() {
cout << name << " is meowing." << endl;
}
};
int main() {
Dog myDog(3, "Buddy");
Cat myCat(2, "Whiskers");
myDog.eat(); // Output: Buddy is eating.
myDog.bark(); // Output: Buddy is barking.
myCat.eat(); // Output: Whiskers is eating.
myCat.meow(); // Output: Whiskers is meowing.
return 0;
}
In this hierarchical inheritance in C++ program, we define the Animal class with common attributes (age, name) and a common behavior (eat()). Dog and Cat inherit from Animal, gaining access to age, name, and the ability to eat(). Finally, Dog adds its unique bark() method, while Cat adds its unique meow() method.
If you wish to learn how to code in C++, you can check out upGrad’s software engineering courses.
When it comes to hierarchy inheritance in C++, the creation and destruction of objects follow a specific order, much like a chain reaction. This strict order is crucial to ensure that objects are constructed and destroyed in a consistent and predictable way.
It guarantees that the derived class constructor can rely on the base class having already been constructed, allowing it to safely use inherited members. It also ensures that during destruction, the derived class can clean up its own resources before the base class releases the underlying memory.
The destruction process reverses this order:
Let's revisit our Animal, Dog, and Cat example to see constructors and destructors in action:
class Animal {
public:
Animal(int age, string name) { // Base constructor
this->age = age;
this->name = name;
cout << "Animal constructor called for " << name << endl;
}
~Animal() { // Base destructor
cout << "Animal destructor called for " << name << endl;
}
// ... rest of the class
};
//Similar constructors and destructors for Dog and Cat...
In C++, the way a derived class inherits from a base class determines how accessible the base class's members (variables and functions) are within the derived class and to the outside world. These visibility modes are controlled by the keywords public, protected, and private used in the inheritance syntax.
This is the most intuitive and commonly used inheritance mode. It allows the derived class to extend the base class's functionality while maintaining the same level of access control.
Inheritance syntax:
class DerivedClass : public BaseClass { ... };
Access rules:
Protected inheritance restricts the access of public members to the derived class and any further derived classes (grandchildren, etc.). It's useful when you want to expose certain members only to descendants while hiding them from external code.
Inheritance syntax:
class DerivedClass : protected BaseClass { ... };
Access rules:
Private inheritance treats the base class as an implementation detail of the derived class. Inherited members are essentially hidden within the derived class and cannot be accessed directly by its objects or any further derived classes. This is often used when you want to reuse code from the base class without exposing its interface to the outside world.
Inheritance syntax:
class DerivedClass : private BaseClass { ... };
Access rules:
In hierarchical inheritance, derived classes often need to modify or specialize the behavior of methods inherited from the base class. This is where overriding comes in. Overriding allows a derived class to provide its own implementation for a function that is already defined in its base class.
To enable overriding, you must declare the base class function as virtual. A virtual function acts as a placeholder, signaling to the compiler that derived classes might provide their own specific implementations. This is a crucial ingredient for polymorphism, the ability of objects of different classes to be treated as objects of a common base class.
The override keyword (introduced in C++11) is a specifier used in the derived class's function declaration. It serves two purposes:
Function overriding in hierarchical inheritance real time example:
Code:
#include <iostream>
#include <cmath> // For M_PI
using namespace std;
class Shape {
public:
virtual double area() const { return 0.0; }
virtual double perimeter() const { return 0.0; }
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) : width(width), height(height) {}
double area() const override { return width * height; }
double perimeter() const override { return 2 * (width + height); }
private:
double width;
double height;
};
class Circle : public Shape {
public:
Circle(double radius) : radius(radius) {}
double area() const override { return M_PI * radius * radius; }
double perimeter() const override { return 2 * M_PI * radius; }
private:
double radius;
};
int main() {
Shape* shapes[] = {new Rectangle(4, 5), new Circle(3) };
for (Shape* s : shapes) {
cout << "Area: " << s->area() << ", Perimeter: " << s->perimeter() << endl;
}
// Release memory (crucial for objects created with 'new')
for (Shape* s : shapes) {
delete s;
}
return 0;
}
You can try out the above hierarchical inheritance in C++ example yourself to experiment with override. In this example, the base class Shape declares area() and perimeter() as virtual functions. The default implementation returns 0.0. Rectangle overrides these functions with its own specific calculations.
The main function creates an array of Shape pointers, which can point to objects of any derived class (Rectangle, Circle, etc.). When area() or perimeter() is called on a Shape pointer, the correct version of the function is dynamically determined at runtime based on the actual object type (polymorphism).
Hierarchical inheritance in C++ is not just a theoretical concept, it is a practical skill that can elevate your C++ programming. The best way to solidify your understanding is to put it into practice.
Also, we should choose wisely between public, protected, and private inheritance to control access to inherited members and tailor your class relationships. Finally, always remember the strict order of their execution to ensure proper object initialization and cleanup.
If you wish to learn programming languages such as C++, you can check out upGrad’s computer science programs such as the Master’s in Computer Science Program.
Hierarchical inheritance is an object-oriented concept where multiple derived classes inherit properties and behaviors from a single base class.
Derived classes inherit the members (variables and functions) of the base class and can add their own unique members.
It promotes code reusability, simplifies maintenance, and models real-world relationships effectively.
Use the syntax class DerivedClass : public BaseClass { ... };, specifying the access mode (public, protected, or private).
It organizes classes into a tree-like structure, representing a "is-a" relationship, and promotes modular code design.
It's used in many software systems, like modeling biological classifications, organizing employee hierarchies, or representing geometric shapes.
Author
Start Learning For Free
Explore Our Free Software Tutorials and Elevate your Career.
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918045604032
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.