Many classes in a program are variations of each other. Circles, rectangles and triangles are all shapes that have an area. Cars and bikes are vehicles. Savings and current accounts are bank accounts. Inheritance lets a derived class build on a base class: it receives the base class's members and adds or changes what it needs.
The real power comes from polymorphism. If the base class declares a function virtual, each derived class can provide its own version, and code that holds a base-class reference or pointer automatically calls the right one. One loop over a list of shapes can then calculate every area correctly, whatever kind of shape each one is.
In this lesson you'll create derived classes, pass values to base constructors, override virtual functions safely with override, build abstract classes with pure virtual functions, and learn why a base class needs a virtual destructor.
Deriving a class
class Animal {
protected:
string name;
public:
Animal(const string& n) : name(n) {}
string getName() const { return name; }
};
class Dog : public Animal {
public:
Dog(const string& n) : Animal(n) {}
string fetch() const { return name + " fetches the ball"; }
};class Dog : public Animalmakes Dog a derived class with public inheritance: Animal's public members stay public in Dog.protectedmembers are hidden from outside code but visible to derived classes, sofetch()can usename.- A derived constructor calls the base constructor in its initializer list:
: Animal(n). The base part is always built first.
virtual functions and override
To let derived classes replace a function and have the replacement used through a base reference, mark it virtual in the base class:
class Shape {
public:
virtual double area() const { return 0; }
};
class Circle : public Shape {
double r;
public:
Circle(double r) : r(r) {}
double area() const override { return 3.14159 * r * r; }
};Write override on the derived version. If the signature doesn't exactly match a virtual function in the base, for example because you forgot const, the compiler reports an error instead of silently creating a different function.
Polymorphism through references and pointers
Polymorphism only works through a reference or pointer to the base class:
void printArea(const Shape& s) {
cout << s.area() << endl; // calls Circle::area for a Circle
}If you pass a derived object by value to a function that takes a Shape, only the Shape part is copied, a problem called slicing, and the base version runs. To keep different kinds of objects in one container, store pointers, usually smart pointers: vector<unique_ptr<Shape>>, as the smart pointers lesson explains.
Abstract classes and virtual destructors
A pure virtual function has = 0 instead of a body. It forces every derived class to provide its own version:
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() = default;
};A class with at least one pure virtual function is abstract: you can't create a Shape directly, only objects of derived classes such as Circle.
Notice the virtual ~Shape(). Whenever a class has virtual functions and objects may be deleted through a base pointer, give it a virtual destructor, so that the derived class's destructor runs too. Without it, deleting a Circle through a Shape* is undefined behaviour.
C++ Inheritance Syntax
Inheritance syntax
class Base {
public:
Base(int x) : x(x) {}
virtual void act() const { ... }
virtual double size() const = 0; // pure virtual
virtual ~Base() = default;
protected:
int x;
};
class Derived : public Base {
public:
Derived(int x) : Base(x) {}
void act() const override { ... }
double size() const override { return x; }
};C++ Inheritance Summary
class Derived : public Baseinherits Base's members;protectedmembers are visible to derived classes.- Call the base constructor in the derived class's initializer list.
- Mark functions
virtualin the base andoverridein derived classes. - Polymorphism works through base references and pointers; passing by value slices objects.
= 0makes a pure virtual function and an abstract class; give polymorphic bases a virtual destructor.
C++ Inheritance Examples
Each example shows the code, the output it produces and what each part does.
Animals that speak differently
#include <iostream>
#include <string>
using namespace std;
class Animal {
protected:
string name;
public:
Animal(const string& n) : name(n) {}
virtual string sound() const { return "..."; }
void speak() const { cout << name << " says " << sound() << endl; }
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
Dog(const string& n) : Animal(n) {}
string sound() const override { return "Woof"; }
};
class Cat : public Animal {
public:
Cat(const string& n) : Animal(n) {}
string sound() const override { return "Meow"; }
};
int main() {
Dog rex("Rex");
Cat tom("Tom");
Animal mystery("Mystery");
rex.speak();
tom.speak();
mystery.speak();
return 0;
}Rex says Woof
Tom says Meow
Mystery says ...Line-by-line explanation
- Line 10sound() is virtual, so derived classes can replace it.
- Line 11speak() is written once in the base class, but calls whichever sound() the object has.
- Line 18Dog overrides sound().
- Line 24Cat overrides it too.
An abstract Shape with polymorphism
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Shape {
public:
virtual double area() const = 0;
virtual string name() const = 0;
virtual ~Shape() = default;
};
class Rectangle : public Shape {
double w, h;
public:
Rectangle(double w, double h) : w(w), h(h) {}
double area() const override { return w * h; }
string name() const override { return "Rectangle"; }
};
class Circle : public Shape {
double r;
public:
Circle(double r) : r(r) {}
double area() const override { return 3.14159 * r * r; }
string name() const override { return "Circle"; }
};
int main() {
vector<unique_ptr<Shape>> shapes;
shapes.push_back(make_unique<Rectangle>(3, 4));
shapes.push_back(make_unique<Circle>(1));
double total = 0;
for (const auto& s : shapes) {
cout << s->name() << ": " << s->area() << endl;
total += s->area();
}
cout << "Total: " << total << endl;
return 0;
}Rectangle: 12
Circle: 3.14159
Total: 15.1416Line-by-line explanation
- Lines 8 to 9Pure virtual functions make Shape abstract; every shape must provide both.
- Line 10A virtual destructor, because shapes are deleted through Shape pointers.
- Lines 30 to 32One vector holds different kinds of shapes through smart pointers.
- Lines 35 to 38Each call goes to the right override: polymorphism.
The slicing problem
#include <iostream>
using namespace std;
class Base {
public:
virtual string who() const { return "Base"; }
virtual ~Base() = default;
};
class Derived : public Base {
public:
string who() const override { return "Derived"; }
};
void byValue(Base b) { cout << "By value: " << b.who() << endl; }
void byReference(const Base& b) { cout << "By reference: " << b.who() << endl; }
int main() {
Derived d;
byValue(d);
byReference(d);
return 0;
}By value: Base
By reference: DerivedLine-by-line explanation
- Line 15Passing by value copies only the Base part of the object.
- Line 16Passing by reference keeps the real object, so the override runs.
Common C++ Inheritance Mistakes
Forgetting virtual in the base class
class Shape {
public:
double area() const { return 0; } // not virtual
};class Shape {
public:
virtual double area() const { return 0; }
};Without virtual, a Shape reference always calls Shape::area, even for a Circle.
A signature that doesn't match
class Circle : public Shape {
double area() override { ... } // error: no matching virtual (missing const)
};class Circle : public Shape {
double area() const override { ... }
};override turns a silent bug into a clear compile error.
No virtual destructor in a polymorphic base
class Shape {
public:
virtual double area() const = 0;
}; // deleting a Circle through Shape* is undefined behaviourclass Shape {
public:
virtual double area() const = 0;
virtual ~Shape() = default;
};C++ Inheritance in Real Projects
Polymorphism in real C++
Game engines such as Unreal give every object in a level a common base class with virtual functions like Tick() and Draw(). GUI frameworks call a virtual paint() on every widget, and plugin systems load classes that implement an abstract interface. The standard library's stream classes, like ostream, also use inheritance, which is why the same << works for cout and for files.
C++ Inheritance FAQ
How do I call the base class version of an overridden function?
Prefix the call with the base class name: inside Dog::speak(), Animal::speak() runs Animal's version even though Dog overrides it. That's handy when the derived version should add to the base behaviour rather than replace it, as in return Animal::speak() + " Woof";.
Are constructors inherited in C++?
Not automatically. A derived class normally writes its own constructors and passes the arguments on, as in Dog(const string& n) : Animal(n) {}. If the derived class adds no new data, using Animal::Animal; inside it inherits all of Animal's constructors in one line.
Can a class inherit from more than one class in C++?
Yes: struct Duck : Flyer, Swimmer { ... }; gives Duck the members of both. It works well for small, independent pieces of behaviour, but it gets complicated when two parents share a base class of their own, the "diamond" problem, which needs virtual inheritance. Many designs keep to a single base class plus abstract interface classes.
What does final mean in C++?
On a virtual function, final stops any further class from overriding it: void f() final;. On a class, as in class Dog final : public Animal, it stops anyone deriving from that class at all. The compiler reports an error if the rule is broken, which documents your design and can help the compiler avoid some virtual calls.
What is the difference between public, protected and private inheritance?
The keyword after the colon limits how the base class's members appear from outside. With public inheritance, public members stay public, which is what you want for "is a" relationships. With protected or private inheritance, the base's public members become protected or private in the derived class, so outside code can't treat a derived object as a base object. Private inheritance is rare; a member variable usually expresses the same idea more clearly.
C++ Inheritance Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the line so Car inherits publicly from Vehicle.
class Car : Vehicle {
};
Complete the base class so derived classes can override sound().
class Animal {
public:
string sound() const { return "..."; }
};
What does this print?
struct A { virtual string hi() const { return "A"; } virtual ~A() = default; };
struct B : A { string hi() const override { return "B"; } };
// in main:
B b;
const A& ref = b;
cout << ref.hi();
What makes a class abstract?
What is object slicing?
C++ Inheritance Quiz
5 questions to check what you learned.
How does a derived class call its base class's constructor?
- base(args) inside the body
- super(args)
- It can't
- In the initializer list: Derived(int x) : Base(x) {}
What does
overridedo?- Makes a function virtual
- Hides the base function from all code
- Asks the compiler to check that the function overrides a virtual base function
- Makes the function faster
Who can access a protected member?
- The class itself and its derived classes
- Any code
- Only the class itself
- Only main
Why does a polymorphic base class need a virtual destructor?
- To speed up deletion
- Destructors must always be virtual
- To allow copying
- So deleting a derived object through a base pointer also runs the derived destructor
Through which kinds of variables does polymorphism work?
- Only by-value base objects
- Base-class references and pointers
- Only global variables
- Only const objects