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