Inheritance

Inheritance lets a new class build on an existing one: a SavingsAccount is an Account with interest; a Button is a Widget you can click. The derived class gets the base class's members and adds or specialises behaviour.

Deriving a class

C++
#include <iostream>
#include <string>
#include <utility>

class Account {
public:
    Account(std::string owner, double balance) : balance_(balance), owner_(std::move(owner)) {}
    void deposit(double amount) { if (amount > 0) balance_ += amount; }
    double balance() const { return balance_; }
    const std::string& owner() const { return owner_; }
protected:
    double balance_;          // accessible to derived classes
private:
    std::string owner_;
};

class SavingsAccount : public Account {
public:
    SavingsAccount(std::string owner, double balance, double rate)
        : Account(std::move(owner), balance), rate_(rate) {}        // construct the base first
    void add_interest() { balance_ += balance_ * rate_; }
private:
    double rate_;
};

int main() {
    SavingsAccount s{"Ana", 1000, 0.03};
    s.deposit(500);                  // inherited from Account
    s.add_interest();                // added by SavingsAccount
    std::cout << s.owner() << ": " << s.balance() << '\n';
}
Output
Ana: 1545

class SavingsAccount : public Account means every SavingsAccount is an Account. The derived constructor calls the base constructor in its initialiser list.

Access levels

Member isAccessible from the class itselfFrom derived classesFrom outside
publicyesyesyes
protectedyesyesno
privateyesnono

Prefer keeping data private even in base classes and giving derived classes protected member functions to work with; protected data lets every derived class break the base class's rules.

Construction and destruction order

C++
#include <iostream>

struct Base {
    Base() { std::cout << "Base constructed\n"; }
    ~Base() { std::cout << "Base destroyed\n"; }
};

struct Derived : Base {
    Derived() { std::cout << "Derived constructed\n"; }
    ~Derived() { std::cout << "Derived destroyed\n"; }
};

int main() {
    Derived d;
}
Output
Base constructed
Derived constructed
Derived destroyed
Base destroyed

The base part is built first and destroyed last — like the foundations of a building.

Hiding vs. overriding

A derived class can declare a function with the same name as one in its base. Without virtual (next lesson), the version called depends on the declared type, not the real object — usually not what you want:

C++
#include <iostream>

struct Animal {
    void speak() const { std::cout << "...\n"; }
};

struct Dog : Animal {
    void speak() const { std::cout << "Woof\n"; }
};

int main() {
    Dog d;
    d.speak();
    const Animal& a = d;
    a.speak();          // calls Animal::speak: no virtual dispatch
}
Output
Woof
...

Using base-class members

Call a base version explicitly with Base::function(), and bring base constructors into the derived class with using:

C++
#include <iostream>
#include <string>

class Logger {
public:
    explicit Logger(std::string prefix) : prefix_(std::move(prefix)) {}
    void log(const std::string& msg) const { std::cout << prefix_ << msg << '\n'; }
private:
    std::string prefix_;
};

class TimestampLogger : public Logger {
public:
    using Logger::Logger;                         // inherit the constructors
    void log(const std::string& msg) const {
        Logger::log("[12:00] " + msg);            // reuse the base version
    }
};

int main() {
    TimestampLogger log{"app: "};
    log.log("started");
}
Output
app: [12:00] started

Inheritance or composition?

Inheritance models "is-a" relationships and is the right tool for polymorphism. When one class merely uses another — a Car has an Engine — make it a member instead (composition). Composition is simpler, more flexible and easier to change, so prefer it unless you need to treat derived objects through a base-class interface.

final

Marking a class final forbids deriving from it; marking a virtual function final forbids further overriding. Use it when a class isn't designed to be extended.

Try it yourself

Create a base class Employee with a name and salary, and a derived Manager with a bonus. Print both people's total pay.

Try it yourself · main.cpp
Edit the code, copy it into main.cpp, then compile and run it with c++ -std=c++20 -Wall main.cpp -o main && ./main. How to set up a C++ compiler
Output
Priya: 52000
Tom: 69000