Inheritance In C++
Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class (derived class) to inherit properties and behaviors from another class (base class). In C++, inheritance can be categorized into three types based on the access level of the inherited members: public, private, and protected inheritance.
Access Modifiers
In C++, access modifiers are keywords used to specify the accessibility of class members (variables and functions) from outside the class. There are three access modifiers in C++: public, private, and protected.
-
Public Access Modifier - When a class member is declared as public, it can be accessed from outside the class through objects of that class. Public members are accessible from anywhere in the program, including outside the class and its derived classes.
-
Private Access Modifier - When a class member is declared as private, it can only be accessed by other members of the same class.
-
Protected Access Modifier - When a class member is declared as protected, it can be accessed by other members of the same class and its derived classes.
Example Code:
#include <iostream>
using namespace std;
class MyClass {
public:
// Public member
int publicMember;
// Public member function
void publicFunction() {
cout << "Public Function" << endl;
}
private:
// Private member
int privateMember;
// Private member function
void privateFunction() {
cout << "Private Function" << endl;
}
protected:
// Protected member
int protectedMember;
// Protected member function
void protectedFunction() {
cout << "Protected Function" << endl;
}
};
int main() {
MyClass obj;
// Accessing public members
obj.publicMember = 10;
obj.publicFunction();
// Private members are not accessible outside the class
// obj.privateMember = 20; // Error: privateMember is inaccessible
// obj.privateFunction(); // Error: privateFunction() is inaccessible
// Protected members are not accessible outside the class
// obj.protectedMember = 30; // Error: protectedMember is inaccessible
// obj.protectedFunction(); // Error: protectedFunction() is inaccessible
return 0;
}Output:
Public FunctionIn this example:
- The publicMember and publicFunction() are accessible from outside the class.
- The privateMember and privateFunction() are private members and are not accessible from outside the class.
- The protectedMember and protectedFunction() are protected members and are not accessible from outside the class but can be accessed by derived classes.
Derived Class Declaration
A derived class is declared by specifying the base class from which it inherits using a colon : followed by the access specifier (public, private, or protected) and the base class name.
Here's the general syntax:
class DerivedClass : accessSpecifier BaseClass {
// Class members and methods
};Public Inheritance
In public inheritance, all public members of the base class become public members of the derived class, and all protected members of the base class become protected members of the derived class. However, the private members of the base class remain inaccessible in the derived class.
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
class Derived : public Base {
// publicMember and protectedMember are accessible here
// privateMember is not accessible here
};Private Inheritance
In private inheritance, all public and protected members of the base class become private members of the derived class. This means that they are not accessible outside the derived class.
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
class Derived : private Base {
// publicMember and protectedMember are private members of Derived
// privateMember is not accessible here
};Protected Inheritance
In protected inheritance, all public and protected members of the base class become protected members of the derived class. This means that they are accessible within the derived class and its derived classes but not outside of them.
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
class Derived : protected Base {
// publicMember and protectedMember are protected members of Derived
// privateMember is not accessible here
};Example Code:
Here's an example demonstrating inheritance in C++:
#include <iostream>
using namespace std;
// Base class
class Base {
public:
int x = 7;
protected:
int y = 5;
private:
int privateMember;
};
// Derived class using public inheritance
class DerivedPublic : public Base {
public:
//DerivedPublic Constructor
DerivedPublic(){
cout<<"DerivedPublic Invoked"<<endl;
}
void display() {
cout << "DerivedPublic: x = " << x << endl;
cout << "DerivedPublic: y = " << y << endl;
// privateMember is not accessible here
}
};
// Derived class using private inheritance
class DerivedPrivate : private Base {
public:
//DerivedPrivate Constructor
DerivedPrivate(){
cout<<"DerivedPrivate Invoked"<<endl;
}
void display() {
cout << "DerivedPrivate: x = " << x << endl;
cout << "DerivedPrivate: y = " << y << endl;
// privateMember is not accessible here
}
};
// Derived class using protected inheritance
class DerivedProtected : protected Base {
public:
//DerivedProtected Constructor
DerivedProtected(){
cout<<"DerivedProtected Invoked"<<endl;
}
void display() {
cout << "DerivedProtected: x = " << x << endl;
cout << "DerivedProtected: y = " << y << endl;
// privateMember is not accessible here
}
};
int main() {
DerivedPublic derivedPublic;
derivedPublic.display();
DerivedPrivate derivedPrivate;
// derivedPrivate.display(); // Error: display() is inaccessible
DerivedProtected derivedProtected;
// derivedProtected.display(); // Error: display() is inaccessible
return 0;
}Output:
DerivedPublic Invoked
DerivedPublic: x = 7
DerivedPublic: y = 5
DerivedPrivate Invoked
DerivedProtected InvokedExplanation:
-
For DerivedPublic class (public inheritance):
- DerivedPublic class inherits publicly from Base class. Therefore, both x and y of the Base class are accessible in the DerivedPublic class.
- The DerivedPublic class constructor is invoked when an object of DerivedPublic class is created.
- The display() function of DerivedPublic class prints the values of x and y.
-
For DerivedPrivate class (private inheritance):
- DerivedPrivate class inherits privately from Base class. This means that all members of Base class become private members of DerivedPrivate class, making them inaccessible outside DerivedPrivate class.
- The DerivedPrivate class constructor is invoked when an object of DerivedPrivate class is created.
- Attempting to call the display() function results in an error because it's inaccessible outside DerivedPrivate.
-
For DerivedProtected class (protected inheritance):
- DerivedProtected class inherits protectedly from Base class, making x and y protected members of DerivedProtected class.
- The DerivedProtected class constructor is invoked when an object of DerivedProtected class is created.
- Similar to DerivedPrivate class, the display() function is inaccessible outside DerivedProtected class.
Friend Function
In C++, a friend function is a function that is not a member of a class but has access to the class's private and protected members. When a function is declared as a friend of a class, it can access private and protected members of that class as if it were a member function of that class. This provides flexibility in defining functions that need access to private or protected members without being members of the class itself.
A friend function of a base class does not have direct access to members of a derived class, even if those members are accessible to the base class. To access members of a derived class, the friend function needs to be declared as a friend in the derived class as well.
Base Class With Friend Function:
#include <iostream>
using namespace std;
// Base class
class Base {
private:
int x = 10;
protected:
int y = 20;
public:
friend void baseFriendFunction(const Base&); // Declaration of friend function
};
// Friend function definition
void baseFriendFunction(const Base& obj) {
cout << "Accessing x from baseFriendFunction: " << obj.x << endl;
cout << "Accessing y from baseFriendFunction: " << obj.y << endl;
}
int main() {
Base baseObj;
baseFriendFunction(baseObj); // Accessing Base class private and protected members
return 0;
}Output:
Accessing x from baseFriendFunction: 10
Accessing y from baseFriendFunction: 20Explanation:
- In this code, we have the Base class with private and protected members.
- We define a friend function baseFriendFunction that takes a const Base& reference as a parameter to access private and protected members of the Base class.
- Inside the main() function, we create an object baseObj of the Base class.
- We then call the baseFriendFunction with baseObj as an argument.
- The baseFriendFunction function accesses the private and protected members of baseObj, printing their values.
Derived Class with Friend Function:
#include <iostream>
using namespace std;
// Base class
class Base {
private:
int x = 10;
protected:
int y = 20;
};
// Derived class
class Derived : public Base {
private:
int p = 30;
protected:
int q = 40;
public:
friend void derivedFriendFunction(const Derived&); // Declaration of friend function
};
// Friend function definition for Derived class
void derivedFriendFunction(const Derived& obj) {
cout << "Accessing p from derivedFriendFunction: " << obj.p << endl;
cout << "Accessing q from derivedFriendFunction: " << obj.q << endl;
}
int main() {
Derived derivedObj;
derivedFriendFunction(derivedObj); // Accessing Derived class private and protected members
return 0;
}Output:
Accessing p from derivedFriendFunction: 30
Accessing q from derivedFriendFunction: 40Explanation:
- In this code, we have two classes: Base and Derived, where Derived publicly inherits from Base.
- We define a friend function derivedFriendFunction to access private and protected members of the Derived class.
- Inside the main() function, we create an object derivedObj of the Derived class.
- We then call the derivedFriendFunction with derivedObj as an argument.
- The derivedFriendFunction function accesses the private and protected members of the Derived class, printing their values.
Friend Classes
Friend classes in C++ provide a way to grant access to the private and protected members of one class to another class. When a class is declared as a friend of another class, it can access private and protected members of that class, just like the members of the class itself. This feature is often used when two or more classes need to share data or functionality that is not intended to be publicly accessible.
Here's a brief overview of friend classes:
- Access to Private and Protected Members: A friend class has access to all the private and protected members of the class it is declared as a friend of.
- Declaration Syntax: To declare a friend class, use the
friendkeyword followed by the class declaration inside the class that is granting friendship. - Bidirectional Friendship: Friendship is not symmetric. If class A is a friend of class B, it doesn't imply that class B is automatically a friend of class A. Friendship must be explicitly declared in both directions if needed.
#include <iostream>
using namespace std;
class A {
private:
int privateDataA;
public:
A(){
privateDataA = 5;
}
friend class B; // Declaring class B as a friend of class A
};
class B {
public:
void accessPrivateDataA(A &objA) {
cout << "Accessing privateDataA from class B: " << objA.privateDataA << endl;
}
};
int main() {
A objA;
B objB;
objB.accessPrivateDataA(objA); // Class B accessing private data of class A
return 0;
}Output:
Accessing privateDataA from class B: 5In this example:
- class B is declared as a friend of class A using the friend keyword.
- class B can now access the private member privateDataA of class A.
- The accessPrivateDataA method in class B accesses the private data of class A through an object of class A.
Forms Of Inheritance
Inheritance allows a class to inherit properties and behaviors (methods) from another class. There are different forms of inheritance in C++:
Single Inheritance

A derived class inherits from only one base class.
#include <iostream>
using namespace std;
// Base class
class Base {
public:
void display() {
cout << "Base class display function" << endl;
}
};
// Derived class inheriting from Base
class Derived : public Base {
public:
void show() {
cout << "Derived class show function" << endl;
}
};
int main() {
Derived derivedObj;
derivedObj.display(); // Accessing Base class function
derivedObj.show(); // Accessing Derived class function
return 0;
}Output:
Base class display function
Derived class show functionExplanation:
- In this code, Derived class inherits publicly from Base.
- The output displays the function calls to both the base class function display() and the derived class function show().
Multiple Inheritance

A derived class inherits from more than one base class.
#include <iostream>
using namespace std;
// Base class 1
class Base1 {
public:
void display1() {
cout << "Base1 class display function" << endl;
}
};
// Base class 2
class Base2 {
public:
void display2() {
cout << "Base2 class display function" << endl;
}
};
// Derived class inheriting from Base1 and Base2
class Derived : public Base1, public Base2 {
public:
void show() {
cout << "Derived class show function" << endl;
}
};
int main() {
Derived derivedObj;
derivedObj.display1(); // Accessing Base1 class function
derivedObj.display2(); // Accessing Base2 class function
derivedObj.show(); // Accessing Derived class function
return 0;
}Output:
Base1 class display function
Base2 class display function
Derived class show functionExplanation:
- In this code, Derived class inherits from both Base1 and Base2.
- The output displays the function calls to each base class function display1() and display2() and the derived class function show().
Multilevel Inheritance

A derived class inherits from another derived class, creating a hierarchy of classes.
#include <iostream>
using namespace std;
// Base class
class Base {
public:
void display() {
cout << "Base class display function" << endl;
}
};
// Derived class inheriting from Base
class Derived : public Base {
public:
void show() {
cout << "Derived class show function" << endl;
}
};
// Another derived class inheriting from Derived
class AnotherDerived : public Derived {
public:
void print() {
cout << "AnotherDerived class print function" << endl;
}
};
int main() {
AnotherDerived derivedObj;
derivedObj.display(); // Accessing Base class function
derivedObj.show(); // Accessing Derived class function
derivedObj.print(); // Accessing AnotherDerived class function
return 0;
}Output:
Base class display function
Derived class show function
AnotherDerived class print functionExplanation:
- In this code, AnotherDerived class inherits from Derived, which in turn inherits from Base.
- The output displays the function calls to each class function display(), show(), and print(), demonstrating the multilevel inheritance hierarchy.
Hierarchical Inheritance

Multiple derived classes inherit from a single base class.
#include <iostream>
using namespace std;
// Base class
class Base {
public:
void display() {
cout << "Base class display function" << endl;
}
};
// Derived class 1 inheriting from Base
class Derived1 : public Base {
public:
void show1() {
cout << "Derived1 class show1 function" << endl;
}
};
// Derived class 2 inheriting from Base
class Derived2 : public Base {
public:
void show2() {
cout << "Derived2 class show2 function" << endl;
}
};
int main() {
Derived1 derived1Obj;
Derived2 derived2Obj;
derived1Obj.display(); // Accessing Base class function through Derived1 object
derived2Obj.display(); // Accessing Base class function through Derived2 object
derived1Obj.show1(); // Accessing Derived1 class function
derived2Obj.show2(); // Accessing Derived2 class function
return 0;
}Output:
Base class display function
Base class display function
Derived1 class show1 function
Derived2 class show2 functionExplanation:
- In this code, both Derived1 and Derived2 classes inherit from Base.
- The output displays the function calls to each class function display(), show1(), and show2(), demonstrating the hierarchical inheritance where multiple derived classes inherit from a single base class.
Hybrid Inheritance

A combination of two or more types of inheritance.
#include <iostream>
using namespace std;
// Base class
class Base {
public:
void display() {
cout << "Base class display function" << endl;
}
};
// Derived class 1 inheriting from Base
class Derived1 : public Base {
public:
void show1() {
cout << "Derived1 class show1 function" << endl;
}
};
// Derived class 2 inheriting from Base
class Derived2 : public Base {
public:
void show2() {
cout << "Derived2 class show2 function" << endl;
}
};
// Derived class 3 inheriting from Derived1 and Derived2
class Derived3 : public Derived1, public Derived2 {
public:
void print() {
cout << "Derived3 class print function" << endl;
}
};
int main() {
Derived3 derivedObj;
derivedObj.display(); // Accessing Base class function through Derived3 object
derivedObj.show1(); // Accessing Derived1 class function
derivedObj.show2(); // Accessing Derived2 class function
derivedObj.print(); // Accessing Derived3 class function
return 0;
}Output:
Base class display function
Derived1 class show1 function
Derived2 class show2 function
Derived3 class print functionExplanation:
- In this code, Derived3 class inherits from both Derived1 and Derived2, which in turn inherit from Base.
- The output displays the function calls to each class function display(), show1(), show2(), and print(), demonstrating hybrid inheritance where multiple inheritance forms are combined.
Virtual Base Class
Multiple inheritance occurs when a class inherits from more than one base class. The diamond problem specifically arises in situations where a class inherits from two or more classes that have a common ancestor. This can lead to ambiguity in the inheritance hierarchy because the derived class indirectly inherits from the common ancestor through multiple paths. This ambiguity can cause issues during compilation or lead to unexpected behavior in the program.
#include <iostream>
using namespace std;
// Define a base class
class Base {
public:
void display() {
cout << "Base class\n";
}
};
// Define two classes, Derived1 and Derived2, both inheriting from Base
class Derived1 : public Base {
public:
// Additional members and methods...
};
class Derived2 : public Base {
public:
// Additional members and methods...
};
// Define a class, MultipleDerived, inheriting from both Derived1 and Derived2
class MultipleDerived : public Derived1, public Derived2 {
public:
// Additional members and methods...
};
int main() {
MultipleDerived obj;
obj.display(); // Error: ambiguous call to 'display'
return 0;
}Output:
Error: ambiguous call to 'display'In this code:
- We have a base class Base with a simple method display.
- Two classes Derived1 and Derived2 inherit from Base.
- Another class MultipleDerived inherits from both Derived1 and Derived2.
- The MultipleDerived class now has two instances of the Base class due to the multiple inheritance paths.
- When we try to call display directly on an object of MultipleDerived, it results in a compilation error due to ambiguity. Both Derived1 and Derived2 provide their own version of Base, leading to confusion.
To resolve this ambiguity, we can use virtual inheritance.
Virtual base classes provide a solution to the diamond problem by ensuring that there's only one instance of the common ancestor class shared among the derived classes. When a class is inherited virtually, it means that the derived classes share a single instance of the virtual base class, rather than each having their own separate instance. This sharing of the base class instance prevents ambiguity and ensures that each derived class has access to a single, consistent instance of the shared base class.
#include <iostream>
using namespace std;
// Define a base class
class Base {
public:
void display() {
cout << "Base class\n";
}
};
// Define the classes with virtual inheritance
class Derived1 : virtual public Base {
// Additional members and methods...
};
class Derived2 : virtual public Base {
// Additional members and methods...
};
// Define a class, MultipleDerived, inheriting from both Derived1 and Derived2
class MultipleDerived : public Derived1, public Derived2 {
// Additional members and methods...
};
int main() {
MultipleDerived obj;
obj.display(); // No ambiguity now, calls display from Base
return 0;
}Ouput:
Base classIn this code:
- Derived1 and Derived2 both inherit virtually from Base.
- MultipleDerived inherits from both Derived1 and Derived2.
- Due to virtual inheritance, there's only one shared instance of Base among all classes in the inheritance hierarchy.
- Now, calling display() on an object of MultipleDerived will correctly call the display() method from the shared Base class, avoiding ambiguity.
Abstract Class
An abstract class in C++ is a class that cannot be instantiated on its own. It serves as a blueprint for other classes and typically contains one or more pure virtual functions. A pure virtual function is a function declared in the base class that has no implementation and must be overridden by derived classes.
#include <iostream>
using namespace std;
// Abstract base class
class Shape {
public:
virtual void draw() = 0;
};
// Concrete derived class Rectangle
class Rectangle : public Shape {
public:
void draw() {
cout << "Drawing rectangle..." << endl;
}
};
// Concrete derived class Circle
class Circle : public Shape {
public:
void draw() {
cout << "Drawing circle..." << endl;
}
};
int main() {
Rectangle rec;
Circle cir;
rec.draw();
cir.draw();
return 0;
}Output:
Drawing rectangle...
Drawing circle...Explanation:
- The code defines an abstract base class Shape with a pure virtual function draw().
- The draw() function in the Shape class has no implementation (pure virtual function), indicating that any derived class must override it.
- Two concrete derived classes Rectangle and Circle inherit from the Shape class.
- Both Rectangle and Circle classes override the draw() function according to their respective shapes.
- In the main() function, objects of Rectangle and Circle are created.
- When draw() is called on the rec object (of type Rectangle), it invokes the draw() function specific to rectangles, printing "Drawing rectangle...".
- Similarly, when draw() is called on the cir object (of type Circle), it invokes the draw() function specific to circles, printing "Drawing circle...".
Advantage and disadvantage of Inheritance
Advantages
- Code Reusability: Inheritance allows classes to inherit attributes and methods from other classes, promoting code reusability and reducing redundancy.
- Extensibility: It enables the creation of new classes that are built upon existing classes, allowing for easy extension and modification of functionality without modifying the existing code.
- Polymorphism: Inheritance facilitates polymorphic behavior, where objects of derived classes can be treated as objects of their base class, leading to flexibility in programming and improved code organization.
- Modularity: It promotes a modular approach to software design by breaking down complex systems into smaller, manageable components, making the codebase easier to understand and maintain.
Disadvantages
- Complexity: Inheritance hierarchies can become complex and difficult to understand, especially in large projects, leading to maintenance challenges and potential bugs.
- Tight Coupling: Excessive use of inheritance can lead to tight coupling between classes, making the codebase less flexible and more difficult to refactor.
- Inheritance Pollution: Subclasses inherit all members (both data and methods) of their base class, which can lead to inheritance pollution and potential conflicts if not managed properly.
- Inflexibility: Changes to the base class can have unintended consequences on derived classes, potentially requiring modifications to multiple parts of the codebase, which can be time-consuming and error-prone.