C++ Inheritance

Creating new classes based on existing classes

🧬 What is Inheritance?

Inheritance allows creating new classes based on existing classes, inheriting properties and methods. Child classes extend parent functionality while promoting code reuse, hierarchy organization, and the "is-a" relationship concept.


// Base class
class Animal {
public:
    void eat() { cout << "Eating..."; }
};

// Derived class
class Dog : public Animal {
public:
    void bark() { cout << "Woof!"; }
};
                                    

Benefits:

✓ Code Reusability

✓ Hierarchical Organization

✓ Extensibility

Types of Inheritance

📏

Single

One child inherits from one parent

class Child : public Parent {
    // Child class
};
🌳

Multiple

One child inherits from multiple parents

class Child : public Parent1, 
              public Parent2 {
};
🔗

Multilevel

Chain of inheritance (grandparent-parent-child)

class A {};
class B : public A {};
class C : public B {};
💎

Hybrid

Combination of multiple inheritance types

// Mix of single + multiple
class D : public B, public C {};

🔹 Single Inheritance

Single inheritance allows a derived class to inherit members and behaviors from one base class, forming an "is-a" relationship. A Car class can derive from Vehicle, inheriting methods like start() ("Vehicle starting...") and adding its own specifics like honk() ("Beep beep!") and doorCount. This promotes code reuse and logical hierarchy—a Car is a Vehicle. The output shows accessing inherited properties ("Brand: Toyota, Year: 2023") alongside derived attributes ("Doors: 4"). Single inheritance simplifies design but limits a class to one direct base, avoiding the complexity of multiple inheritance.

#include <iostream>
using namespace std;

// Base class
class Vehicle {
protected:
    string brand;
    int year;

public:
    Vehicle(string b, int y) : brand(b), year(y) {}
    
    void start() {
        cout << "Vehicle starting..." << endl;
    }
    
    void displayInfo() {
        cout << "Brand: " << brand << ", Year: " << year << endl;
    }
};

// Derived class
class Car : public Vehicle {
private:
    int doors;

public:
    Car(string b, int y, int d) : Vehicle(b, y), doors(d) {}
    
    void honk() {
        cout << "Beep beep!" << endl;
    }
    
    void displayCarInfo() {
        displayInfo();  // Inherited method
        cout << "Doors: " << doors << endl;
    }
};

int main() {
    Car myCar("Toyota", 2023, 4);
    
    myCar.start();        // Inherited method
    myCar.honk();         // Own method
    myCar.displayCarInfo();
    
    return 0;
}

Output:

Vehicle starting...

Beep beep!

Brand: Toyota, Year: 2023

Doors: 4

🔹 Multiple Inheritance

Multiple inheritance enables a class to inherit from more than one base class, combining their capabilities. A Duck class can inherit from both Flyable (with method fly() producing "Flying in the sky!") and Swimmable (with swim() producing "Swimming in water!"), while also defining its own quack(). This models real-world objects with multiple distinct roles. However, it can introduce challenges like the diamond problem (ambiguous base paths) and increased complexity. Careful design using virtual inheritance or interfaces is needed to manage these trade-offs effectively.

#include <iostream>
using namespace std;

class Flyable {
public:
    void fly() {
        cout << "Flying in the sky!" << endl;
    }
};

class Swimmable {
public:
    void swim() {
        cout << "Swimming in water!" << endl;
    }
};

// Multiple inheritance
class Duck : public Flyable, public Swimmable {
public:
    void quack() {
        cout << "Quack quack!" << endl;
    }
};

int main() {
    Duck donald;
    
    donald.fly();    // From Flyable
    donald.swim();   // From Swimmable
    donald.quack();  // Own method
    
    return 0;
}

Output:

Flying in the sky!

Swimming in water!

Quack quack!

🔹 Multilevel Inheritance

Multilevel inheritance creates a chain of derived classes, each extending the previous level, to model increasingly specialized entities. For example, VehicleCarSportsCar forms a hierarchy where each level adds specificity. Vehicle provides basic mobility, Car adds passenger features, and SportsCar introduces high-performance traits. This allows gradual refinement and reuse of code up the chain. While it promotes organized hierarchies, deep chains can become fragile—changes to a middle base class affect all descendants. It's best used for clear, stable "is-a-kind-of" relationships.

#include <iostream>
using namespace std;

// Grandparent class
class Animal {
public:
    void breathe() {
        cout << "Breathing..." << endl;
    }
};

// Parent class
class Mammal : public Animal {
public:
    void feedMilk() {
        cout << "Feeding milk to babies" << endl;
    }
};

// Child class
class Dog : public Mammal {
public:
    void bark() {
        cout << "Woof woof!" << endl;
    }
};

int main() {
    Dog myDog;
    
    myDog.breathe();   // From Animal (grandparent)
    myDog.feedMilk();  // From Mammal (parent)
    myDog.bark();      // Own method
    
    return 0;
}

Output:

Breathing...

Feeding milk to babies

Woof woof!

🔹 Virtual Inheritance

Virtual inheritance in C++ is designed to resolve the diamond problem that arises in multiple inheritance. When two parent classes inherit from a common grandparent, virtual inheritance ensures only one instance of the grandparent exists in the final derived class. This prevents ambiguous calls to inherited members and maintains a single, shared base subobject. For example, a Bat class inheriting virtually from both Mammal and Bird avoids duplicate Animal base objects, ensuring consistent behavior for methods like eat(), walk(), and fly().

#include <iostream>
using namespace std;

class Animal {
public:
    void eat() {
        cout << "Animal eating" << endl;
    }
};

// Virtual inheritance prevents duplicate Animal copies
class Mammal : virtual public Animal {
public:
    void walk() {
        cout << "Walking on land" << endl;
    }
};

class Bird : virtual public Animal {
public:
    void fly() {
        cout << "Flying in air" << endl;
    }
};

// Bat inherits from both Mammal and Bird
class Bat : public Mammal, public Bird {
public:
    void hangUpsideDown() {
        cout << "Hanging upside down" << endl;
    }
};

int main() {
    Bat myBat;
    
    myBat.eat();              // Only one Animal::eat() exists
    myBat.walk();             // From Mammal
    myBat.fly();              // From Bird
    myBat.hangUpsideDown();   // Own method
    
    return 0;
}

Output:

Animal eating

Walking on land

Flying in air

Hanging upside down

🧠 Test Your Knowledge

Which inheritance type creates a chain of classes?