Inheritance — Quick Reference
C++ inheritance cheatsheet — access specifiers, virtual dispatch, override/final, virtual destructor, abstract classes, multiple inheritance, and common pitfalls.
Access Specifiers in Inheritance
cpp
class Base { public: int pub; protected: int prot; private: int priv; };
class D_pub : public Base { /* pub→public, prot→protected, priv→inaccessible */ };
class D_prot : protected Base { /* pub→protected, prot→protected, priv→inaccessible */ };
class D_priv : private Base { /* pub→private, prot→private, priv→inaccessible */ };Virtual Dispatch
cpp
struct Animal {
virtual std::string speak() const = 0; // pure virtual
virtual void breathe() const { std::println("breathe"); } // virtual default
void live() const { std::println("live"); } // non-virtual
virtual ~Animal() = default; // ALWAYS virtual in polymorphic base
};
struct Dog : Animal {
std::string speak() const override { return "woof"; }
void breathe() const override { std::println("pant"); }
};
Animal* a = new Dog{};
a->speak(); // Dog::speak() — virtual dispatch
a->breathe(); // Dog::breathe() — virtual dispatch
a->live(); // Animal::live() — no dispatch (non-virtual)
delete a; // ~Dog() called — safe because destructor is virtualoverride and final
cpp
struct Base {
virtual void foo(int) = 0;
virtual void bar() {}
};
struct Mid : Base {
void foo(int) override {} // override checks signature
void bar() final {} // bar cannot be overridden further
// void foo(float) override; // ERROR: no virtual to override
};
struct Leaf final : Mid { // Leaf cannot be subclassed
// void bar() override; // ERROR: bar is final
};Constructor/Destructor Order
cpp
struct A { A(){puts("A()");} ~A(){puts("~A()");} };
struct B : A { B(){puts("B()");} ~B(){puts("~B()");} };
struct C : B { C(){puts("C()");} ~C(){puts("~C()");} };
C c;
// A() B() C() — construction: base → derived
// ~C() ~B() ~A() — destruction: derived → baseCalling Base Class Method
cpp
struct Animal {
virtual std::string describe() const { return "Animal"; }
};
struct Dog : Animal {
std::string describe() const override {
return Animal::describe() + " + Dog"; // explicit base call
}
};Abstract Class Rules
cpp
struct Interface {
virtual void go() = 0; // pure virtual
virtual ~Interface() = default; // virtual dtor
};
// Interface{}; // ERROR: cannot instantiate abstract class
// static_assert(std::is_abstract_v<Interface>);Multiple Inheritance (Interfaces)
cpp
struct IDrawable { virtual void draw() = 0; virtual ~IDrawable() = default; };
struct IClickable { virtual void click() = 0; virtual ~IClickable() = default; };
struct IResizable { virtual void resize() = 0; virtual ~IResizable() = default; };
class Button : public IDrawable, public IClickable, public IResizable {
void draw() override { std::println("draw"); }
void click() override { std::println("click"); }
void resize() override { std::println("resize"); }
};Virtual Inheritance (Diamond Fix)
cpp
struct Animal { std::string name; };
struct Dog : virtual Animal {};
struct Robot : virtual Animal {};
struct Cyborg : Dog, Robot {}; // one Animal subobject shared
Cyborg c;
c.name = "Fido"; // unambiguous — one shared AnimalPitfalls
cpp
// ❌ Slicing: derived state lost when assigned to base by value
Dog d;
Animal a = d; // sliced: only Animal part copied
// ❌ Non-virtual destructor: UB when deleting derived through base ptr
struct Bad { virtual void f(){} }; // forgot virtual ~Bad()
// delete (Bad*)new Dog{}; // UB
// ❌ Calling virtual function in constructor/destructor
struct Unsafe {
Unsafe() { init(); } // calls Unsafe::init(), NOT derived override
virtual void init() {}
};