🧬 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.