C++ Inheritance Object-Oriented Programming
OOP Concept

C++ Inheritance: Complete Guide with Examples

Master C++ inheritance: single, multiple, multilevel, hierarchical inheritance. Learn access specifiers, polymorphism, virtual functions, and best practices for OOP.

Single Inheritance

One Base Class

Multiple Inheritance

Multiple Base Classes

Multilevel

Chain of Inheritance

Hierarchical

Multiple Derived Classes

C++ Tutorial · Inheritance

Inheritance reuses and extends existing classes. Learn access levels, constructor chaining, function hiding, and how to design sensible IS-A hierarchies without abuse.

C++ inheritance infographic: single inheritance, multilevel, hierarchical, multiple inheritance, access specifiers, and base-derived class diagrams
C++ inheritance visual guide — base and derived classes, inheritance types, access levels, and IS-A relationships for OOP interview preparation.

What you will learn

  • Derive classes with public/protected/private inheritance
  • Order constructor and destructor calls
  • Override and hide base member functions
  • Use using-declarations to expose overloads
  • Design shallow hierarchies with clear responsibilities

Why this topic matters

Inheritance questions test design sense—not just syntax. Diamond problem and access specifiers are interview favorites.

Key terms & indexing

C++ inheritance derived class C++ public inheritance constructor chaining C++

Introduction to Inheritance

Inheritance is a fundamental Object-Oriented Programming (OOP) concept that allows a class to acquire properties and behaviors of another class. It promotes code reusability and establishes relationships between classes.

Why Use Inheritance?
  • Code reusability and reduction
  • Establishes "is-a" relationships
  • Supports polymorphism
  • Creates hierarchical classifications
  • Extends existing functionality
  • Improves code organization
Inheritance Components
  • Base Class: Parent class being inherited from
  • Derived Class: Child class that inherits
  • Access Specifiers: public, private, protected
  • Member Functions: Inherited methods
  • Data Members: Inherited attributes
Inheritance Relationship Flow
1
Base Class: Define common properties and behaviors
2
Derived Class: Inherits from base class
3
Extension: Add new properties/methods
4
Override: Modify inherited behaviors
5
Utilization: Use inherited functionality

C++ Inheritance Types

The following table compares all inheritance types in C++ with their syntax, use cases, and characteristics:

Type Syntax When to Use Characteristics
Single Inheritance class Derived : public Base { }; Simple "is-a" relationships, basic reuse One base class, one derived class
Multiple Inheritance class Derived : public Base1, public Base2 { }; Combine features from multiple classes Multiple base classes, one derived class
Multilevel Inheritance class A {}; class B: public A {}; class C: public B {}; Hierarchical systems, layered abstractions Chain of inheritance (grandparent-parent-child)
Hierarchical Inheritance class Base {}; class D1: public Base {}; class D2: public Base {}; Multiple specialized classes from one base One base class, multiple derived classes
Hybrid Inheritance Combination of multiple types Complex class hierarchies, special cases Multiple + hierarchical, uses virtual inheritance
Virtual Inheritance class Derived : virtual public Base { }; Solve diamond problem in multiple inheritance Prevents duplicate base class instances

1. Access Specifiers in Inheritance

Access specifiers determine how base class members are accessible in derived classes. C++ provides three access specifiers: public, protected, and private.

Access Specifier Syntax
// Base class
class Base {
public:
    int publicVar;
protected:
    int protectedVar;
private:
    int privateVar;
};

// Derived class with different access modes
class Derived : public Base {
    // public inheritance:
    // publicVar remains public
    // protectedVar remains protected
    // privateVar is inaccessible
};

class Derived : protected Base {
    // protected inheritance:
    // publicVar becomes protected
    // protectedVar remains protected
    // privateVar is inaccessible
};

class Derived : private Base {
    // private inheritance:
    // publicVar becomes private
    // protectedVar becomes private
    // privateVar is inaccessible
}

Examples

1. Public inheritance
class Base { public: int x; };
class D : public Base { };
2. Protected member
class Base { protected: int x; };
class D : public Base { void f(){ x=1; } };
3. Private inaccessible
class Base { private: int x; };
// D cannot access x
4. Protected inheritance
class D : protected Base { };
// public members become protected
5. Private inheritance
class D : private Base { };
// public members become private
6. Using declaration
class D : private Base {
public:
    using Base::show;
};
Access Specifier Rules:
  • public: Accessible everywhere
  • protected: Accessible in derived classes
  • private: Accessible only in own class
  • Choose public inheritance for "is-a" relationships
  • Use private inheritance for "implemented-in-terms-of"
Common Mistakes:
  • Forgetting access specifiers
  • Using private inheritance incorrectly
  • Trying to access private base members
  • Not providing interfaces for private/protected inheritance
  • Confusing "has-a" with "is-a" relationships

2. Single Inheritance

Single inheritance is the simplest form where a derived class inherits from only one base class.

Basic Syntax
class Base {
    // Base class members
};

class Derived : access-specifier Base {
    // Derived class members
};

Examples

1. Base and derived
class Person { string name; };
class Student : public Person { int roll; };
2. Constructor chain
Student(string n,int r) : Person(n), roll(r) {}
3. Method override
void display() override { cout << name; }
4. is-a relationship
Student s("Ali", 101);
s.display();
5. Protected reuse
class Employee : public Person {
    double salary;
};
6. Call base method
void info() { Person::display(); cout << roll; }

Key Points: Single Inheritance

  • Most common and straightforward inheritance type
  • Establishes clear "is-a" relationship
  • Derived class can override base class methods
  • Constructors called from base to derived
  • Destructors called from derived to base

3. Multiple Inheritance

Multiple inheritance allows a class to inherit from more than one base class, combining their features.

Basic Syntax
class Base1 {
    // First base class
};

class Base2 {
    // Second base class
};

class Derived : public Base1, public Base2 {
    // Inherits from both Base1 and Base2
};

Examples

1. Two base classes
class A { public: void fa(); };
class B { public: void fb(); };
class C : public A, public B {};
2. Combine interfaces
class Printable { virtual void print()=0; };
class Saveable { virtual void save()=0; };
class File : public Printable, public Saveable {};
3. Ambiguity risk
class X { int v; };
class Y { int v; };
class Z : public X, public Y {};
4. Scope resolution
Z z;
z.X::v = 1;
z.Y::v = 2;
5. MI employee
class Worker : public Person, public Payable {};
6. Implement both
void print() override {}
void save() override {}
Advantages
  • Combine features from multiple classes
  • Greater code reuse
  • Flexible class design
  • Model complex real-world relationships
Disadvantages
  • Diamond problem (ambiguous inheritance)
  • Increased complexity
  • Constructor order complications
  • Harder to maintain

4. Multilevel Inheritance

Multilevel inheritance involves a chain of inheritance where a class is derived from another derived class.

Basic Syntax
class Grandparent {
    // Base class
};

class Parent : public Grandparent {
    // Intermediate class
};

class Child : public Parent {
    // Most derived class
};

Examples

1. Three levels
class A {};
class B : public A {};
class C : public B {};
2. Grandparent access
class Animal { protected: int age; };
class Mammal : public Animal {};
class Dog : public Mammal {};
3. Constructor order
Dog() : Mammal(), Animal() {}
4. Override at leaf
void speak() override { cout << "Bark"; }
5. Chain display
cout << age;  // from Animal
6. Deep but shallow design
Prefer composition over very deep trees
Constructor/Destructor Order in Multilevel Inheritance:
  • Constructors: Base → Intermediate → Derived (top to bottom)
  • Destructors: Derived → Intermediate → Base (bottom to top)
  • Each constructor initializes its own members first
  • Virtual destructors ensure proper cleanup
  • Use initialization lists for efficiency

5. Hierarchical Inheritance

Hierarchical inheritance involves multiple derived classes inheriting from a single base class.

Examples

1. One parent many children
class Shape { virtual double area()=0; };
class Circle : public Shape {};
class Rect : public Shape {};
2. Shared interface
Shape* s = new Circle(3);
cout << s->area();
3. Employee hierarchy
class Employee { };
class Manager : public Employee {};
class Dev : public Employee {};
4. Different bonuses
double bonus() override { return salary*0.2; }
5. Vector of base ptr
vector team;
6. Polymorphic loop
for (auto* e : team) e->display();
When to Use Hierarchical Inheritance:
  • When you have a general category with specific subcategories
  • When multiple classes share common functionality
  • For implementing polymorphism through base class pointers
  • When creating class libraries or frameworks
  • For database entity relationships

6. Virtual Functions and Polymorphism

Polymorphism allows objects of different classes to be treated as objects of a common base class. Virtual functions enable runtime polymorphism.

Virtual Function

Function that can be overridden in derived classes.

class Base {
public:
    virtual void show() {
        cout << "Base show";
    }
};

class Derived : public Base {
public:
    void show() override {
        cout << "Derived show";
    }
};
Pure Virtual Function

Makes class abstract (cannot be instantiated).

class Abstract {
public:
    virtual void pure() = 0;
};

class Concrete : public Abstract {
public:
    void pure() override {
        // Implementation
    }
};
Virtual Destructor

Ensures proper cleanup of derived objects.

class Base {
public:
    virtual ~Base() {
        // Cleanup
    }
};

class Derived : public Base {
public:
    ~Derived() override {
        // Derived cleanup
    }
};

Examples

1. virtual function
virtual void draw() { cout << "Shape"; }
2. override draw
void draw() override { cout << "Circle"; }
3. Base pointer
Shape* p = new Circle();
p->draw();
4. Pure virtual
virtual double area() = 0;
5. Abstract cannot new
// Shape s;  // error
6. Runtime binding
delete p;  // calls correct destructor if virtual
Important Rules for Virtual Functions:
  • Always declare destructor as virtual in base classes
  • Use override keyword (C++11) for clarity
  • Virtual functions have runtime overhead
  • Constructors cannot be virtual
  • Static functions cannot be virtual
  • Use final keyword (C++11) to prevent further overriding

7. Diamond Problem and Virtual Inheritance

The diamond problem occurs in multiple inheritance when a class inherits from two classes that both inherit from the same base class. Virtual inheritance solves this.

Examples

1. Diamond layout
class A { int x; };
class B : public A {};
class C : public A {};
class D : public B, public C {};
2. Ambiguous member
// D has two copies of A::x
3. Virtual inheritance
class B : virtual public A {};
class C : virtual public A {};
4. Single A subobject
class D : public B, public C {};
5. Call shared base
D d;
d.x = 5;  // one x
6. Prefer interface
Use abstract interfaces to reduce diamond risk
Virtual Inheritance Guidelines:
  • Use virtual inheritance to solve diamond problem
  • Most derived class calls virtual base constructor directly
  • Virtual base constructor called before non-virtual base constructors
  • Adds overhead (virtual base pointer)
  • Use only when diamond inheritance is necessary
  • Consider composition over multiple inheritance

8. Best Practices and Common Mistakes

Best Practices
  • Use public inheritance for "is-a" relationships
  • Prefer composition over multiple inheritance
  • Always make destructors virtual in base classes
  • Use override keyword (C++11) for clarity
  • Keep inheritance hierarchies shallow (2-3 levels)
  • Use abstract base classes for interfaces
  • Document inheritance relationships clearly
Common Mistakes
  • Forgetting virtual destructors
  • Deep inheritance hierarchies
  • Using multiple inheritance unnecessarily
  • Confusing "has-a" with "is-a" relationships
  • Not using access specifiers correctly
  • Circular inheritance dependencies
  • Ignoring the diamond problem

Examples

1. Shallow hierarchy
class Animal {};
class Dog : public Animal {};
2. Composition
class Car { Engine engine; };
3. virtual destructor
virtual ~Resource() = default;
4. override clarity
void run() override {}
5. Avoid deep chain
// ChocolateLabrador extends Labrador... too deep
6. Liskov respect
Base* b = new Derived();
b->use();  // behaves correctly

Frequently asked questions

What is multiple inheritance?

One class inherits from several bases—possible diamond problem; virtual inheritance can resolve shared bases.

Can private members be inherited?

Yes, but not accessible in derived classes unless using protected or public inheritance with accessible base members.

When should I prefer composition over inheritance?

When HAS-A fits better than IS-A—composition avoids tight coupling and deep fragile hierarchies.