optional · CSS study notes
Inheritance (extended, incl. Forms of Inheritance + diamond problem)
- Single inheritance: one derived class from one base class
- Multiple inheritance: one derived class from more than one base class (C++ supports this; some languages like Java do not, using interfaces instead — a useful comparative fact)
- Access levels in inheritance:
public(preserves accessibility),protected(accessible within class and derived classes, not outside),private(accessible only within the defining class) — protected members are specifically visible to derived classes but not to external code - Method overriding: a derived class provides its own implementation of a method already defined in its base class (same signature)
Types of Inheritance (C++ Examples)
Single inheritance — one base, one derived:
class Animal
{
public:
void eat() {}
};
class Dog : public Animal
{
public:
void bark() {}
};
Multiple inheritance — one derived class, 2+ base classes (C++ allows this; Java/C# don't, and use interfaces instead):
class Flyer
{
public:
void fly() {}
};
class Swimmer
{
public:
void swim() {}
};
class Duck : public Flyer, public Swimmer {}; // Duck can fly() and swim()
Multilevel inheritance — a chain of derivation:
class Animal
{
public:
void eat() {}
};
class Mammal : public Animal
{
public:
void walk() {}
};
class Dog : public Mammal // Dog gets eat() + walk() + bark()
{
public:
void bark() {}
};
Hierarchical inheritance — several derived classes share one base:
class Shape
{
public:
void draw() {}
};
class Circle : public Shape {};
class Square : public Shape {}; // both reuse Shape::draw()
Hybrid inheritance — a mix of the above (e.g. hierarchical + multiple) — often the source of the diamond problem below.
The Diamond Problem & Virtual Base Class
When two base classes (B, C) both derive from the same class A, and D derives from both B and C, D ends up with two separate copies of A — accessing a member of A through D becomes ambiguous:
class A { public: int x; };
class B : public A {};
class C : public A {};
class D : public B, public C {};
// D obj; obj.x = 5; -- ERROR: ambiguous (B::A::x or C::A::x?)
Fix: declare A as a virtual base class in B and C, so D shares a single A subobject:
class A { public: int x; };
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};
// D obj; obj.x = 5; -- OK: only one shared A subobject now
Constructor / Destructor Order
- Constructors run base → derived (the base class constructor always finishes before the derived class constructor body runs)
- Destructors run in the reverse order: derived → base
- This guarantees the base portion of an object is fully built before derived-class code uses it, and isn't torn down while derived-class cleanup might still depend on it
Effect of Inheritance Access Specifier on Base Members
| Base class member | public inheritance | protected inheritance | private inheritance |
|---|---|---|---|
public | stays public | becomes protected | becomes private |
protected | stays protected | stays protected | becomes private |
private | never accessible in derived class | never accessible | never accessible |
MCQ Trap
- C++ supports multiple inheritance; many other OOP languages (e.g., Java) restrict classes to single inheritance and use interfaces instead.
- The diamond problem only arises with multiple/hybrid inheritance sharing a common ancestor — fixed by declaring the shared base
virtual - Default inheritance mode is
privatefor aclassandpublicfor astruct— easy to miss on an MCQ
Forms of Inheritance (all 5 — the book lists this as its own heading)
| Form | Structure | Example |
|---|---|---|
| Single | One base → one derived | Animal → Dog |
| Multiple | One derived ← two or more bases | FlyingRobot ← Flyable • Robot |
| Multilevel | Chain: base → derived → further derived | Animal → Mammal → Dog |
| Hierarchical | One base → multiple independent derived classes | Shape → Circle, Square, Triangle |
| Hybrid | Combination of two or more forms above (often multiple + hierarchical) | Diamond-shaped hierarchies — can trigger the "diamond problem" (ambiguous inherited member), solved in C++ via virtual inheritance |
// Multilevel inheritance
class Animal
{
public:
void eat() { cout << "eats food\n"; }
};
class Mammal : public Animal
{
public:
void walk() { cout << "walks\n"; }
};
class Dog : public Mammal
{
public:
void bark() { cout << "barks\n"; }
};
// Dog object has access to eat(), walk(), AND bark()
// Hierarchical inheritance
class Shape
{
public:
virtual double area() = 0;
};
class Circle : public Shape {}; // one derived class
class Square : public Shape {}; // another, independent, derived class
Diamond problem (hybrid inheritance) — worth knowing for CSS:
class A { public: int x; };
class B : public A {};
class C : public A {};
class D : public B, public C {}; // D now has TWO copies of A::x -- ambiguous!
// Fixed with virtual inheritance:
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {}; // now only ONE shared copy of A::x
Self-Test Questions
- Name all 5 forms of inheritance and give a one-line example of each.
- What is the "diamond problem," and how does C++ resolve it?
- What's the difference between
protectedandprivatewhen it comes to a derived class's access?