In the previous chapter, we saw a small glimpse of inheritance while exploring the four pillars of OOP, where a ShortVideo class reused properties from a Content class without rewriting them. That small example was only the beginning, since inheritance is one of the most powerful tools C++ offers for organizing related classes and avoiding repeated code.
Inheritance allows a new class to acquire the properties and behavior of an already existing class. The existing class is referred to as the base class, sometimes also called the parent class, while the new class built on top of it is called the derived class, or child class. This relationship models a very natural real-world pattern, where a more specific category shares common traits with a broader, more general category, while also having some traits of its own.
In this tutorial, you will learn the syntax for creating a derived class, understand the different access modes used during inheritance, explore the five types of inheritance supported in C++, and see how constructors behave when a derived class object is created.
Imagine a channel management system that needs to represent different kinds of content: standard videos, short videos, and live streams. All three share common properties such as a title and a channel name, but each also has some properties unique to itself, like duration for a standard video or viewer count for a live stream.
Without inheritance, you would need to repeat the shared properties like title and channel name inside every single class separately, which duplicates code and makes future updates harder, since a single change would need to be applied in multiple places. Inheritance solves this by letting all three specific classes share a single common base class, keeping the code centralized and easier to maintain.
To create a derived class in C++, the class name is followed by a colon, an access mode, and the name of the base class it is inheriting from.
class DerivedClassName : accessMode BaseClassName {
// additional members
};
#include <iostream>
using namespace std;
class Content {
public:
string title;
string channel = "CS Engineering Gyan";
void showBasicInfo() {
cout << "Title: " << title << ", Channel: " << channel << endl;
}
};
class StandardVideo : public Content {
public:
int durationMinutes;
void showDuration() {
cout << "Duration: " << durationMinutes << " minutes" << endl;
}
};
int main() {
StandardVideo lecture;
lecture.title = "Inheritance in C++";
lecture.durationMinutes = 18;
lecture.showBasicInfo();
lecture.showDuration();
return 0;
}
Title: Inheritance in C++, Channel: CS Engineering Gyan Duration: 18 minutes
Here, StandardVideo inherits from Content, gaining access to the title, channel, and showBasicInfo without redefining them, while also adding its own durationMinutes property and showDuration function.
The access mode used while inheriting, whether public, protected, or private, controls how the inherited members are treated inside the derived class. Public inheritance is by far the most commonly used mode, and it keeps the access level of inherited members largely unchanged.
| Inheritance Mode | Effect on Public Members of Base Class | Effect on Protected Members of Base Class |
|---|---|---|
| public | Remain public in the derived class | Remain protected in the derived class |
| protected | Become protected in the derived class | Remain protected in the derived class |
| private | Become private in the derived class | Become private in the derived class |
Regardless of the inheritance mode used, private members of the base class are never directly accessible inside the derived class, and can only be accessed indirectly through public or protected member functions defined in the base class.
Single inheritance is the simplest form, where one derived class inherits from exactly one base class. The earlier StandardVideo and Content example is itself an example of single inheritance.
#include <iostream>
using namespace std;
class Channel {
public:
string name = "CS Engineering Gyan";
};
class Subscriber : public Channel {
public:
string subscriberName;
void greet() {
cout << subscriberName << " is subscribed to " << name << endl;
}
};
int main() {
Subscriber viewer;
viewer.subscriberName = "Aman";
viewer.greet();
return 0;
}
Aman is subscribed to CS Engineering Gyan
Multilevel inheritance occurs when a derived class itself becomes the base class for another class, forming a chain of inheritance across multiple levels. Each level down the chain inherits everything from all the levels above it.
#include <iostream>
using namespace std;
class Content {
public:
string channel = "CS Engineering Gyan";
};
class Video : public Content {
public:
string title;
};
class Tutorial : public Video {
public:
string topic;
void showTutorialInfo() {
cout << channel << " - " << title << " (" << topic << ")" << endl;
}
};
int main() {
Tutorial cppTutorial;
cppTutorial.title = "Inheritance Explained";
cppTutorial.topic = "C++ OOP";
cppTutorial.showTutorialInfo();
return 0;
}
CS Engineering Gyan - Inheritance Explained (C++ OOP)
Here, Tutorial inherits from Video, which itself inherits from Content, so Tutorial ends up with access to members from both classes above it in the chain.
Hierarchical inheritance occurs when multiple derived classes inherit from a single common base class. This is essentially the reverse structure of multilevel inheritance, spreading outward from one base class rather than stacking downward.
#include <iostream>
using namespace std;
class Content {
public:
string channel = "CS Engineering Gyan";
};
class ShortVideo : public Content {
public:
int durationSeconds = 45;
};
class LiveStream : public Content {
public:
int viewerCount = 1200;
};
int main() {
ShortVideo reel;
LiveStream stream;
cout << reel.channel << " short video duration: " << reel.durationSeconds << " seconds" << endl;
cout << stream.channel << " live stream viewers: " << stream.viewerCount << endl;
return 0;
}
CS Engineering Gyan short video duration: 45 seconds CS Engineering Gyan live stream viewers: 1200
Both ShortVideo and LiveStream independently inherit the channel property from the same Content base class, yet each also has its own unique property that the other does not share.
Multiple inheritance allows a single derived class to inherit from more than one base class at the same time. This can be powerful, but it also requires extra care, since it is possible for two base classes to have members with the same name, creating ambiguity.
#include <iostream>
using namespace std;
class Playable {
public:
void play() {
cout << "Playback started" << endl;
}
};
class Downloadable {
public:
void download() {
cout << "Download started" << endl;
}
};
class OfflineVideo : public Playable, public Downloadable {
public:
string title = "C++ Inheritance Basics";
};
int main() {
string channel = "CS Engineering Gyan";
OfflineVideo savedVideo;
cout << channel << " video: " << savedVideo.title << endl;
savedVideo.play();
savedVideo.download();
return 0;
}
CS Engineering Gyan video: C++ Inheritance Basics Playback started Download started
Here, OfflineVideo inherits functionality from two completely separate base classes, Playable and Downloadable, and ends up being able to use methods from both of them together.
Hybrid inheritance is simply a combination of two or more of the inheritance types discussed above, used together within the same class design. For example, a class hierarchy might combine hierarchical inheritance with multiple inheritance to model a more complex real-world relationship.
#include <iostream>
using namespace std;
class Content {
public:
string channel = "CS Engineering Gyan";
};
class Playable {
public:
void play() {
cout << "Now playing" << endl;
}
};
class PremiumVideo : public Content, public Playable {
public:
string title = "Advanced C++ Concepts";
};
int main() {
PremiumVideo exclusiveVideo;
cout << exclusiveVideo.channel << " premium video: " << exclusiveVideo.title << endl;
exclusiveVideo.play();
return 0;
}
CS Engineering Gyan premium video: Advanced C++ Concepts Now playing
This example combines features from two unrelated base classes into a single derived class, illustrating how hybrid inheritance mixes different inheritance patterns as a project's design requires.
When an object of a derived class is created, the base class's constructor runs first automatically, followed by the derived class's own constructor. This ensures that the inherited part of the object is fully set up before the derived class adds anything on top of it.
#include <iostream>
using namespace std;
class Content {
public:
Content() {
cout << "Content object initialized" << endl;
}
};
class Video : public Content {
public:
Video() {
cout << "Video object initialized" << endl;
}
};
int main() {
string channel = "CS Engineering Gyan";
cout << channel << " creating a new video object:" << endl;
Video newVideo;
return 0;
}
CS Engineering Gyan creating a new video object: Content object initialized Video object initialized
Notice the order in the output, since the base class constructor, Content, always finishes running before the derived class constructor, Video, begins its own work, regardless of the order in which the classes are written in the code.
| Advantages | Limitations |
|---|---|
| Reduces duplicate code by allowing classes to reuse existing functionality. | Deep inheritance chains can become difficult to trace and understand. |
| Models natural real-world relationships between general and specific categories. | Multiple inheritance can lead to ambiguity if base classes share member names. |
| Makes it easier to extend existing systems with new, specialized classes. | Overusing inheritance where composition would fit better can lead to rigid designs. |
| Mistake | Correct Practice |
|---|---|
| Trying to access private base class members directly from the derived class. | Use protected or public access, or provide public functions in the base class for controlled access. |
| Assuming the derived class constructor runs before the base class constructor. | Remember that the base class constructor always executes first. |
| Using inheritance purely to reuse unrelated code between two classes. | Use inheritance only when a true general-to-specific relationship exists. |
| Ignoring potential naming conflicts in multiple inheritance. | Explicitly qualify member names with the base class name when ambiguity arises. |
Inheritance allows a derived class to build on top of an existing base class, reusing its properties and behavior while adding its own specialized features. This chapter walked through the basic syntax, the effect of different access modes, and all five types of inheritance supported in C++: single, multilevel, hierarchical, multiple, and hybrid.
We also looked at how constructors behave when derived class objects are created, with the base class constructor always executing first to ensure the inherited portion of the object is properly set up before anything else happens. Used thoughtfully, inheritance is one of the most effective tools for reducing duplicate code and modeling relationships between classes in a natural, readable way.
With inheritance covered, you are now ready to explore polymorphism in C++, which builds on these same class relationships to allow functions and objects to behave differently depending on the situation they are used in.