Lesson 50 of 60 – Inheritance in C++
83%

Inheritance in C++

Inheritance is an important concept of Object-Oriented Programming (OOP). It allows one class to acquire properties and behaviors from another class. The existing class is called the base class, and the new class is called the derived class.

Note: Inheritance promotes code reuse and allows classes to represent relationships between general and specialized objects.

1. What is Inheritance?

Inheritance allows a derived class to reuse accessible members of a base class.

class Animal {

public:

    void eat() {

        std::cout << "Eating";
    }
};

class Dog : public Animal {

};

Here, Dog inherits from Animal.

2. Base Class

The class whose members are inherited is called the base class, also known as the parent class.

class Animal {

public:

    void eat() {

        std::cout << "Eating";
    }
};

In this example, Animal is the base class.

3. Derived Class

The class that inherits from another class is called the derived class, also known as the child class.

class Dog : public Animal {

};

Here, Dog is the derived class.

4. Basic Inheritance Syntax

The basic syntax for inheritance is:

class DerivedClass : accessSpecifier BaseClass {

    // derived class members

};

Example:

class Dog : public Animal {

};

5. Simple Inheritance Example

#include <iostream>

class Animal {

public:

    void eat() {

        std::cout <<
            "Animal is eating";
    }
};

class Dog : public Animal {

public:

    void bark() {

        std::cout <<
            "Dog is barking";
    }
};

int main() {

    Dog dog;

    dog.eat();

    dog.bark();

    return 0;
}

The Dog object can use the inherited eat() function as well as its own bark() function.

6. Code Reuse Through Inheritance

Inheritance allows common functionality to be written once in a base class and reused by derived classes.

class Vehicle {

public:

    void start() {

        std::cout << "Vehicle started";
    }
};

class Car : public Vehicle {

};

class Bike : public Vehicle {

};

Both Car and Bike can use the inherited start() function.

7. Adding New Members to a Derived Class

class Vehicle {

public:

    void start() {

        std::cout <<
            "Vehicle started";
    }
};

class Car : public Vehicle {

public:

    void openTrunk() {

        std::cout <<
            "Trunk opened";
    }
};

The derived class can add its own data members and functions.

8. Single Inheritance

When one derived class inherits from one base class, it is called single inheritance.

class Animal {

};

class Dog : public Animal {

};

This is the simplest form of inheritance.

9. Multilevel Inheritance

When a class is derived from another derived class, it creates a chain of inheritance called multilevel inheritance.

class Animal {

};

class Mammal : public Animal {

};

class Dog : public Mammal {

};

Here:

Animal → Mammal → Dog

10. Multiple Inheritance

When one class inherits from more than one base class, it is called multiple inheritance.

class Father {

public:

    void fatherFeature() {

        std::cout <<
            "Father feature";
    }
};

class Mother {

public:

    void motherFeature() {

        std::cout <<
            "Mother feature";
    }
};

class Child :
    public Father,
    public Mother {

};

The Child class inherits from both Father and Mother.

11. Hierarchical Inheritance

When multiple derived classes inherit from the same base class, it is called hierarchical inheritance.

class Animal {

public:

    void eat() {

        std::cout <<
            "Eating";
    }
};

class Dog : public Animal {

};

class Cat : public Animal {

};

Both Dog and Cat inherit from Animal.

12. Hybrid Inheritance

Hybrid inheritance is a combination of two or more inheritance forms.

For example, a program may combine multiple inheritance with multilevel or hierarchical inheritance.

class A {

};

class B : public A {

};

class C : public A {

};

class D :
    public B,
    public C {

};

Such designs need careful consideration because multiple inheritance can introduce ambiguity.

13. Public Inheritance

With public inheritance, public members of the base class remain public members of the derived class.

class Animal {

public:

    void eat() {

        std::cout << "Eating";
    }
};

class Dog : public Animal {

};

A Dog object can call eat().

14. Private Members and Inheritance

Private members of a base class are not directly accessible inside the derived class.

class Animal {

private:

    int age;

public:

    void setAge(int a) {

        age = a;
    }
};

class Dog : public Animal {

public:

    void test() {

        // age = 10;  // Not allowed
    }
};

The derived class can use appropriate public or protected functions provided by the base class.

15. Protected Members

Protected members can be accessed inside the class and its derived classes.

class Animal {

protected:

    int age;
};

class Dog : public Animal {

public:

    void setAge(int a) {

        age = a;
    }
};

Here, Dog can access the protected member age.

16. Inheritance and Access Specifiers

Base Member Public Inheritance
public Remains public in the derived class.
protected Remains protected in the derived class.
private Not directly accessible in the derived class.

This table describes the usual access effect of public inheritance.

17. Calling Base Class Functions

class Animal {

public:

    void eat() {

        std::cout <<
            "Animal eats";
    }
};

class Dog : public Animal {

public:

    void bark() {

        std::cout <<
            "Dog barks";
    }
};

int main() {

    Dog dog;

    dog.eat();

    dog.bark();

    return 0;
}

The derived object can call accessible inherited members directly.

18. Calling a Base Class Constructor

A derived class constructor can initialize the base class by using the base class constructor in its initializer list.

class Person {

protected:

    std::string name;

public:

    Person(
        std::string n
    )
        : name(n) {
    }
};

class Student : public Person {

public:

    Student(
        std::string n
    )
        : Person(n) {
    }
};

19. Constructor and Destructor Order

When a derived object is created, the base class constructor runs before the derived class constructor.

When the derived object is destroyed, the derived destructor runs before the base destructor.

class Base {

public:

    Base() {

        std::cout <<
            "Base constructor"
            << std::endl;
    }

    virtual ~Base() {

        std::cout <<
            "Base destructor"
            << std::endl;
    }
};

class Derived : public Base {

public:

    Derived() {

        std::cout <<
            "Derived constructor"
            << std::endl;
    }

    ~Derived() {

        std::cout <<
            "Derived destructor"
            << std::endl;
    }
};

20. Inheritance with Data Members

class Person {

protected:

    std::string name;
};

class Student : public Person {

private:

    int marks;

public:

    void setData(
        std::string n,
        int m
    ) {

        name = n;
        marks = m;
    }

    void display() {

        std::cout <<
            name << " "
            << marks;
    }
};

The derived class can use accessible inherited data and its own data.

21. Practical Person and Student Example

#include <iostream>
#include <string>

class Person {

protected:

    std::string name;
    int age;

public:

    Person(
        std::string n,
        int a
    )
        : name(n),
          age(a) {
    }
};

class Student : public Person {

private:

    float marks;

public:

    Student(
        std::string n,
        int a,
        float m
    )
        : Person(n, a),
          marks(m) {
    }

    void display() {

        std::cout <<
            "Name: "
            << name
            << std::endl;

        std::cout <<
            "Age: "
            << age
            << std::endl;

        std::cout <<
            "Marks: "
            << marks;
    }
};

int main() {

    Student student(
        "Amit",
        20,
        88.5
    );

    student.display();

    return 0;
}

22. Inheritance and Function Overriding

A derived class can provide its own implementation of a base class function. When working with virtual functions, this is called overriding.

class Animal {

public:

    virtual void sound() {

        std::cout <<
            "Animal sound";
    }
};

class Dog : public Animal {

public:

    void sound() override {

        std::cout <<
            "Dog barks";
    }
};

The override keyword helps the compiler check that the derived function overrides a virtual base function.

23. Multiple Inheritance Example

class Printer {

public:

    void print() {

        std::cout <<
            "Printing";
    }
};

class Scanner {

public:

    void scan() {

        std::cout <<
            "Scanning";
    }
};

class AllInOne :
    public Printer,
    public Scanner {

};

int main() {

    AllInOne machine;

    machine.print();

    machine.scan();

    return 0;
}

The derived class inherits functionality from both base classes.

24. Diamond Problem

Multiple inheritance can create a diamond problem when two classes inherit from the same base class and another class inherits from both of them.

class A {

};

class B : public A {

};

class C : public A {

};

class D :
    public B,
    public C {

};

Here, D can contain two inheritance paths to A. Virtual inheritance can be used in suitable designs to avoid duplicated base subobjects.

25. Virtual Inheritance

class A {

public:

    int value;
};

class B : virtual public A {

};

class C : virtual public A {

};

class D :
    public B,
    public C {

};

Virtual inheritance makes the common base class subobject shared in the diamond hierarchy.

26. Common Inheritance Mistakes

  • Trying to directly access private base-class members.
  • Using multiple inheritance without considering ambiguity.
  • Forgetting the inheritance access specifier.
  • Confusing inheritance with composition.
  • Calling an overridden function incorrectly.
  • Forgetting a virtual destructor in a polymorphic base class when deletion through a base pointer is intended.
  • Creating unnecessarily deep inheritance hierarchies.

27. Advantages of Inheritance

  • Code Reuse: Common functionality can be placed in a base class.
  • Extensibility: Derived classes can add specialized behavior.
  • Organization: Related classes can be arranged in a hierarchy.
  • Polymorphism: Inheritance works with virtual functions to support runtime polymorphism.
  • Maintainability: Shared behavior can be managed in one base class.

28. Best Practices for Inheritance

  • Use inheritance when there is a genuine "is-a" relationship.
  • Keep base classes focused on common behavior.
  • Use public inheritance when the derived type should be usable as the base type.
  • Prefer protected functions or public interfaces over exposing unnecessary data.
  • Use override when overriding virtual functions.
  • Use a virtual destructor in a polymorphic base class when appropriate.
  • Avoid unnecessarily deep or complicated inheritance hierarchies.
  • Consider composition when a "has-a" relationship is more appropriate.

29. Real-World Uses of Inheritance

  • Person → Student: A student can inherit common person information.
  • Person → Employee: Employee can reuse common person details.
  • Vehicle → Car: Car can inherit common vehicle behavior.
  • Vehicle → Bike: Bike can inherit common vehicle behavior.
  • Animal → Dog: Dog can specialize common animal behavior.
  • Shape → Circle: Circle can specialize common shape behavior.
  • Account → SavingsAccount: A specialized account can reuse common account functionality.

30. Inheritance – Final Summary

Concept Meaning
Inheritance A mechanism through which a class derives accessible members from another class.
Base Class The class whose members are inherited.
Derived Class The class that inherits from another class.
Single Inheritance One derived class inherits from one base class.
Multilevel Inheritance Inheritance occurs through multiple levels.
Multiple Inheritance One class inherits from multiple base classes.
Hierarchical Inheritance Multiple derived classes inherit from one base class.
Virtual Inheritance Helps manage shared base subobjects in certain multiple-inheritance hierarchies.
class Animal {

public:

    virtual void sound() {

        std::cout <<
            "Animal sound";
    }

    virtual ~Animal() = default;
};

class Dog : public Animal {

public:

    void sound() override {

        std::cout <<
            "Dog barks";
    }
};

int main() {

    Dog dog;

    dog.sound();

    return 0;
}

📌 Key Points

  • Inheritance allows a class to derive accessible members from another class.
  • The existing class is called the base class.
  • The new class is called the derived class.
  • Public inheritance commonly represents an "is-a" relationship.
  • Private members of a base class are not directly accessible in the derived class.
  • Protected members can be accessed by derived classes.
  • C++ supports single, multilevel, multiple, hierarchical, and hybrid inheritance forms.
  • Derived classes can add new members and override virtual functions.
  • Constructors run from base to derived, while destruction proceeds from derived to base.
  • Use inheritance carefully and consider composition when a "has-a" relationship is more appropriate.

🧠 Quick Quiz

Question: What is the main purpose of inheritance in C++?