C++ by Example
C++ by Example

Inheritance

2 min read

Inheritance

Inheritance lets one class (the derived class) extend another (the base class), inheriting its members and optionally overriding its behavior. It models "is-a" relationships.

Basic inheritance

#include <iostream>
#include <string>

class Animal {
public:
    std::string name;

    Animal(std::string n) : name(std::move(n)) {}

    void breathe() const {
        std::cout << name << " breathes\n";
    }
};

class Dog : public Animal {
public:
    Dog(std::string n) : Animal(std::move(n)) {}

    void bark() const {
        std::cout << name << " barks\n";
    }
};

int main() {
    Dog d("Rex");
    d.breathe();   // inherited
    d.bark();      // Dog-specific
}

The : public Animal clause makes Dog a public subclass. The Dog constructor calls Animal(n) to initialize the base part — the base constructor must be called before the body runs.

Access specifiers in inheritance

Base member public inheritance protected inheritance private inheritance
public public protected private
protected protected protected private
private not accessible not accessible not accessible

public inheritance is the most common and models a true "is-a" relationship. private inheritance is occasionally used for policy-based design.

Protected members

protected members are accessible within the class and all derived classes, but not from outside:

class Vehicle {
protected:
    int speed = 0;

public:
    int get_speed() const { return speed; }
};

class Car : public Vehicle {
public:
    void accelerate() { speed += 10; }   // OK: speed is protected
};

Constructor chaining

Derived constructors must explicitly invoke the base constructor in their initializer list:

class Shape {
    std::string color;
public:
    Shape(std::string c) : color(std::move(c)) {}
    std::string get_color() const { return color; }
};

class Circle : public Shape {
    double radius;
public:
    Circle(double r, std::string c) : Shape(std::move(c)), radius(r) {}

    double area() const { return 3.14159 * radius * radius; }
};

If no base constructor is explicitly called, the compiler calls the base default constructor. If the base has no default constructor, the code does not compile.

Inheriting constructors (C++11)

using Base::Base; brings all base constructors into the derived class:

class LoggedVector : public std::vector<int> {
public:
    using std::vector<int>::vector;   // inherit all vector constructors

    void log_push(int x) {
        std::cout << "pushing " << x << "\n";
        push_back(x);
    }
};

Slicing

Assigning a derived object to a base object by value slices off the derived parts:

Dog d("Buddy");
Animal a = d;    // slices: a has only the Animal part, loses Dog-specific data

Pass polymorphic objects through pointers or references, never by value.

C++ by Example
C++ by Example

Learn modern C++ through working code. Each chapter introduces one concept — variables, functions, classes, templates, smart pointers, concurrency — with a clear example, a line-by-line explanation, and notes on how it applies in real programs.

View book →