Intermediate⏱️ 10 min📘 Topic 21 of 32

🧬 Inheritance in C++ — Base, Derived and the Diamond Problem

Master C++ inheritance — public/protected/private inheritance, single/multiple inheritance, the diamond problem and virtual inheritance. With examples and interview Q&A.

Inheritance lets one class extend another — reusing fields and methods while adding or overriding behavior.

📜 The basic pattern

class Animal {
public:
  std::string name;
  void eat() { std::cout << name << " eats"; }
};

class Dog : public Animal {
public:
  void bark() { std::cout << name << " barks"; }
};

Dog d;
d.name = "Rex";
d.eat();   // inherited
d.bark();  // own method

🔒 Inheritance access modes

  • public — "is-a" relationship. Public members of base stay public in derived.
  • protected — base's public/protected become protected. Rare.
  • private — "implemented-in-terms-of". All become private. Composition-like.

📚 Single vs multiple inheritance

class Flyer { ... };
class Swimmer { ... };
class Duck : public Flyer, public Swimmer { ... };

💎 The diamond problem

class A { int x; };
class B : public A { };
class C : public A { };
class D : public B, public C { };
// D has TWO copies of A's members — ambiguity!

Fix with virtual inheritance: class B : virtual public A.

💡 "is-a" vs "has-a"

Inheritance models is-a (Dog is-an Animal). Composition models has-a (Car has-an Engine). Prefer composition when in doubt.

💻 Code Examples

Public inheritance — is-a relationship

class Shape {
protected:
  std::string name;
public:
  Shape(std::string n) : name(n) {}
  void describe() { std::cout << "I am a " << name; }
};
class Circle : public Shape {
  double radius;
public:
  Circle(double r) : Shape("Circle"), radius(r) {}
};
Circle c(5);
c.describe();
Output:
I am a Circle

Constructor chaining

class Base {
public:
  Base()  { std::cout << "Base\n"; }
  ~Base() { std::cout << "~Base\n"; }
};
class Derived : public Base {
public:
  Derived()  { std::cout << "Derived\n"; }
  ~Derived() { std::cout << "~Derived\n"; }
};
Derived d;
Output:
Base
Derived
~Derived
~Base

⚠️ Common Mistakes

  • Using inheritance for code reuse instead of 'is-a' — leads to fragile hierarchies. Prefer composition.
  • Forgetting a virtual destructor in a base class — deleting via base pointer leaks derived parts.
  • Multiple inheritance without virtual inheritance — diamond problem causes ambiguity.
  • Public fields in the base class — shifts the encapsulation problem to derived classes.

🎯 Interview Questions

Real questions asked at top product and service-based companies.

Q1.What is inheritance in C++?Beginner
A mechanism where one class (derived) reuses and extends another (base). The derived class inherits the base's public/protected members and can add its own or override behavior.
Q2.What's the difference between public and private inheritance?Intermediate
public: 'is-a' relationship; base's public members remain public in derived. private: 'implemented in terms of'; everything becomes private in derived — derived doesn't expose base interface. Public is far more common.
Q3.What is the diamond problem?Intermediate
When a class inherits from two classes that share a common base, the most-derived class has TWO COPIES of that base — causing ambiguity. Fixed by declaring the shared base as `virtual` in the intermediate classes.
Q4.When should you prefer composition over inheritance?Intermediate
Almost always — unless there's a true 'is-a' relationship and you NEED polymorphism. Composition is more flexible, easier to test, and avoids fragile-base-class issues.
Q5.Why must a base class with virtual functions have a virtual destructor?Advanced
If a derived object is deleted via a base pointer, a non-virtual destructor calls only the base's destructor — derived fields leak. Always declare the destructor virtual in polymorphic base classes.

🧠 Quick Summary

  • Inheritance: Derived reuses + extends Base.
  • Access modes: public (is-a), protected, private.
  • Multiple inheritance is allowed; watch for the diamond problem.
  • Use `virtual` inheritance to fix shared-base ambiguity.
  • Prefer composition unless polymorphism is truly needed.