C++ inheritance
Inheritance lets one class reuse and extend another class.
The original class is called the base class.
The new class is called the derived class.
This post uses only simple single inheritance.
Multiple inheritance and virtual functions are separate topics.
Base class
A base class contains data and functions that can be shared.
Animal is a normal class. It does not know anything about Dog.
Derived class
Use : public BaseClass to inherit.
Dog can use the public functions from Animal.
Dog also adds its own function: bark().
What public inheritance means
This means:
Dog is an Animal.
So a Dog object has the public interface of Animal.
Use public inheritance when the relationship is really is-a.
Good examples:
Dogis anAnimalCaris aVehicleCircleis aShape
Bad example:
Engineis not aCar
For that case, use composition:
Public, protected, and private inheritance
You can replace public with protected or private.
This changes how the base class interface is exposed through the derived class.
| Inheritance | Base public members become |
Common meaning |
|---|---|---|
public Animal |
public in Dog |
Dog is an Animal |
protected Animal |
protected in Dog |
only Dog and derived classes can use the Animal interface |
private Animal |
private in Dog |
Dog uses Animal internally |
Most of the time, use public inheritance.
Example with public inheritance:
Example with private inheritance:
Simple rule:
- use
publicinheritance for normal is-a relationships - use
privateinheritance rarely, when a class is implemented using another class - use
protectedinheritance very rarely
Private data is still private
The derived class does not get direct access to private members of the base class.
Private means:
only the class itself can access it directly.
The derived class should use public or protected functions from the base class.
Protected members
protected means:
- the base class can access it
- derived classes can access it
- outside code cannot access it directly
Use protected carefully. In many cases, private data with public/protected
functions is easier to control.
Constructor chaining
When you create a derived object, C++ constructs the base part first.
Then it constructs the derived part.
Example:
Output:
This line calls the base class constructor:
Read it like this:
- build the
Animalpart usingname - build the
Dogpart usingage
Default base constructor
If the base class has a default constructor, you do not have to call it explicitly.
C++ calls it automatically before the derived constructor body runs.
Output:
This constructor:
is the same as writing:
You need to call the base constructor explicitly when the base constructor needs arguments.
Destructor order
Destruction happens in the opposite order.
Simple demo:
Output:
Base class interface, derived class object
A derived object can be used through the base class public interface.
The object is still a Dog, but it contains an Animal part.
You can also create a Dog, but use it through the Animal interface.
The real object is still a Dog.
But when you access it through Animal& or Animal*, C++ only lets you use the
functions that exist in the Animal interface.
Heap allocation
You can also create the Dog on the heap and store the address in an Animal*.
The object is allocated as a Dog.
The pointer animal only exposes the Animal interface.
For modern C++, prefer smart pointers:
The std::unique_ptr<Dog> deletes the Dog automatically when it goes out of
scope.
Virtual functions change what happens when calling overridden functions through a base reference or pointer. Deleting derived objects through base pointers is also connected to virtual destructors. Those are separate topics.
Quick rules
| Situation | Use |
|---|---|
| A class is a more specific version of another class | public inheritance |
| A class only owns another object | composition |
| Derived class needs to initialize base data | call base constructor in initializer list |
| Base data should not be directly touched | keep it private |
| Derived class needs limited access | use protected carefully |
What is not covered here
This post does not cover virtual functions.
Without virtual functions, inheritance is mostly about:
- reusing code
- sharing a base interface
- constructing base and derived parts correctly
Virtual functions are needed for runtime polymorphism. That should be learned in a separate step.
C++ also does not have a special interface keyword like Java or C#.
In C++, an interface is usually written as an abstract class with pure virtual functions.
Small preview:
The = 0 means the function must be implemented by a derived class.
Interfaces and abstract classes should be learned together in a separate post.