Inheritance in C++

Inheritance lets you create new classes from existing ones. This reuses code and builds relationships between classes. It helps you write less code and make programs easier to manage. This guide shows you how to use inheritance in C++ with clear steps and examples.

c++ inheritance

What is Inheritance in C++?

Inheritance in C++ is a process where one class acquires the properties and behaviors of another class. The class that inherits is the derived class (or subclass). The class it inherits from is the base class (or superclass).

Inheritance offers several key benefits:

  • Code Reusability: You write common code once in the base class. Then, derived classes reuse it without rewriting. This saves time and reduces errors.
  • Reduced Development Time: Reusing existing code speeds up development. You focus on new features instead of duplicating efforts.
  • Easier Maintenance: Changes in the base class apply to all derived classes. This simplifies updates and bug fixes across your program.
  • Improved Readability: Code becomes more organized and easier to understand. You see clear relationships between classes.

How to Implement Inheritance in C++

Implementing inheritance involves declaring a derived class from a base class. Here is the basic syntax:

class DerivedClass : access_specifier BaseClass {
    // Members of DerivedClass
};

Here, access_specifier defines how members of the base class are inherited in the derived class. Common specifiers include public, protected, and private.

Access Specifiers in Inheritance

Access specifiers control member visibility in derived classes:

  • Public Inheritance: Base class public members become public in the derived class. protected members become protected. private members remain private and are not directly accessible.
  • Protected Inheritance: Base class public and protected members become protected in the derived class. private members remain private.
  • Private Inheritance: Base class public and protected members become private in the derived class. private members remain private.

Here is a table summarizing access in derived classes:

Base Class AccessPublic InheritanceProtected InheritancePrivate Inheritance
publicpublicprotectedprivate
protectedprotectedprotectedprivate
privateNot accessibleNot accessibleNot accessible

Types of Inheritance in C++

C++ supports five main types of inheritance. Each type serves different purposes for class relationships and code organization.

1. Single Inheritance

Single inheritance involves one derived class inheriting from one base class. This is the simplest and most common type of inheritance.

Single Inheritance in C++

Example:

You have a Vehicle base class. Then, you create a Car class that inherits from Vehicle.

#include <iostream>

// Base class
class Vehicle {
public:
    void accelerate() {
        std::cout << "Vehicle is accelerating." << std::endl;
    }
};

// Derived class
class Car : public Vehicle {
public:
    void drive() {
        std::cout << "Car is driving." << std::endl;
    }
};

int main() {
    Car myCar;
    myCar.accelerate(); // Inherited from Vehicle
    myCar.drive();      // Member of Car
    return 0;
}

Output:

Vehicle is accelerating.
Car is driving.

In this example, Car inherits accelerate() from Vehicle.

2. Multiple Inheritance

Multiple inheritance lets a derived class inherit from multiple base classes. This combines features from several independent classes into one.

Multiple Inheritance in C++

Example:

You have a Writer class and an Artist class. You create a WriterArtist class that inherits from both.

#include <iostream>

// Base class 1
class Writer {
public:
    void write() {
        std::cout << "Writer is writing a story." << std::endl;
    }
};

// Base class 2
class Artist {
public:
    void draw() {
        std::cout << "Artist is drawing a picture." << std::endl;
    }
};

// Derived class inheriting from Writer and Artist
class WriterArtist : public Writer, public Artist {
public:
    void create() {
        std::cout << "WriterArtist is creating something new." << std::endl;
    }
};

int main() {
    WriterArtist person;
    person.write(); // Inherited from Writer
    person.draw();  // Inherited from Artist
    person.create();
    return 0;
}

Output:

Writer is writing a story.
Artist is drawing a picture.
WriterArtist is creating something new.

WriterArtist has access to write() from Writer and draw() from Artist.

3. Multilevel Inheritance

Multilevel inheritance involves a chain of inheritance. A class inherits from a base class, and then another class inherits from this derived class.

Multilevel Inheritance in C++

Example:

You have a Animal class. Then, Mammal inherits from Animal. Finally, Dog inherits from Mammal.

#include <iostream>

// Grandparent class
class Animal {
public:
    void eat() {
        std::cout << "Animal eats food." << std::endl;
    }
};

// Parent class
class Mammal : public Animal {
public:
    void breathe() {
        std::cout << "Mammal breathes air." << std::endl;
    }
};

// Child class
class Dog : public Mammal {
public:
    void bark() {
        std::cout << "Dog barks loudly." << std::endl;
    }
};

int main() {
    Dog myDog;
    myDog.eat();    // Inherited from Animal
    myDog.breathe(); // Inherited from Mammal
    myDog.bark();
    return 0;
}

Output:

Animal eats food.
Mammal breathes air.
Dog barks loudly.

Here, Dog gets features from both Mammal and Animal.

4. Hierarchical Inheritance

Hierarchical inheritance occurs when multiple derived classes inherit from a single base class. This is useful for creating a family of related classes that share common characteristics.

Hierarchical Inheritance in C++

Example:

You have a Shape base class. Then, Circle and Rectangle both inherit from Shape.

#include <iostream>

// Base class
class Shape {
public:
    void display() {
        std::cout << "This is a shape." << std::endl;
    }
};

// Derived class 1
class Circle : public Shape {
public:
    void drawCircle() {
        std::cout << "Drawing a circle." << std::endl;
    }
};

// Derived class 2
class Rectangle : public Shape {
public:
    void drawRectangle() {
        std::cout << "Drawing a rectangle." << std::endl;
    }
};

int main() {
    Circle myCircle;
    myCircle.display(); // Inherited from Shape
    myCircle.drawCircle();

    Rectangle myRectangle;
    myRectangle.display(); // Inherited from Shape
    myRectangle.drawRectangle();
    return 0;
}

Output:

This is a shape.
Drawing a circle.
This is a shape.
Drawing a rectangle.

Both Circle and Rectangle reuse the display() method from Shape.

5. Hybrid (Virtual) Inheritance

Hybrid inheritance combines two or more types of inheritance. A common form is combining multiple and hierarchical inheritance. This can lead to the “Diamond Problem” where a class inherits common members from two parent classes that themselves share a common grandparent class. C++ solves this using virtual base classes.

Hybrid (Virtual) Inheritance in C++

The Diamond Problem:

Consider A as a base class. B and C inherit from A. Then, D inherits from both B and C. D gets two copies of A‘s members.

#include <iostream>

class A {
public:
    A() { std::cout << "A's constructor called." << std::endl; }
    void func() { std::cout << "A's function." << std::endl; }
};

class B : public A {
public:
    B() { std::cout << "B's constructor called." << std::endl; }
};

class C : public A {
public:
    C() { std::cout << "C's constructor called." << std::endl; }
};

class D : public B, public C {
public:
    D() { std::cout << "D's constructor called." << std::endl; }
};

int main() {
    D obj;
    // obj.func(); // Ambiguous call
    return 0;
}

The call obj.func() is ambiguous because D has two func() methods, one from B and one from C. Both originate from A.

Solution: Virtual Base Classes

You use the virtual keyword to make A a virtual base class for B and C. This ensures D gets only one copy of A‘s members.

#include <iostream>

class A {
public:
    A() { std::cout << "A's constructor called." << std::endl; }
    void func() { std::cout << "A's function." << std::endl; }
};

class B : virtual public A { // Virtual inheritance
public:
    B() { std::cout << "B's constructor called." << std::endl; }
};

class C : virtual public A { // Virtual inheritance
public:
    C() { std::cout << "C's constructor called." << std::endl; }
};

class D : public B, public C {
public:
    D() { std::cout << "D's constructor called." << std::endl; }
};

int main() {
    D obj;
    obj.func(); // Now works
    return 0;
}

Output:

A's constructor called.
B's constructor called.
C's constructor called.
D's constructor called.
A's function.

Using virtual ensures only one A sub-object exists within D.

Best Practices for Inheritance

Use these tips to make your inheritance code better:

  • Favor Composition Over Inheritance: Use inheritance when a clear “is-a” relationship exists (e.g., Car is a Vehicle). Use composition when a “has-a” relationship exists (e.g., Car has an Engine). Composition often leads to more flexible designs.
  • Keep Base Classes Simple: Design base classes with common, generic functionality. Avoid adding too many specific details.
  • Use protected for Internal Access: Use protected members when derived classes need to access base class data, but external code should not.
  • Define Clear Interfaces: Ensure base classes provide a clear interface for derived classes to implement or override. Use virtual functions for this.
  • Avoid Deep Inheritance Hierarchies: Deep hierarchies become complex and difficult to manage. Keep your inheritance trees shallow.
Avatar photo
Great Learning Editorial Team
The Great Learning Editorial Staff includes a dynamic team of subject matter experts, instructors, and education professionals who combine their deep industry knowledge with innovative teaching methods. Their mission is to provide learners with the skills and insights needed to excel in their careers, whether through upskilling, reskilling, or transitioning into new fields.

Academy Pro Subscription

Grab 50% off
on Top Courses - Free Trial Available

×
Scroll to Top