Introduction
Inheritance builds a new class on an existing one. class Dog : public Animal means a Dog is an Animal, with everything an Animal has, plus more. The shared code lives once, in the base class; the derived class adds or changes what is different.
Many classes share most of their code. Inheritance writes the shared part once in a base class, and each derived class adds only what makes it different.
How it works
Base and derived classes
#include <iostream>
#include <string>
using namespace std;
class Animal {
protected:
string name;
public:
Animal(string n) : name(n) {}
void eat() {
cout << name << " is eating" << endl;
}
};
class Dog : public Animal {
int tricks;
public:
Dog(string n) : Animal(n), tricks(0) {}
void fetch() {
tricks++;
cout << name << " fetches the ball (" << tricks << ")" << endl;
}
};
int main() {
Dog rex("Rex");
rex.eat();
rex.fetch();
rex.fetch();
return 0;
}- A
Dogobject contains anAnimalpart. In the visualizer,rexshowsname(from Animal) andtricks(its own) side by side, because the base part sits inside the derived object. rex.eat()calls the inheritedAnimal::eat;rex.fetch()is Dog's own.protectedmembers are like private ones, except that derived classes may use them:Dog::fetchreadsname.
Access and the "is a" test
| Base member | in the derived class | outside, through the derived object |
|---|---|---|
public | yes | yes (with : public inheritance) |
protected | yes | no |
private | no | no |
Use inheritance only when the derived class really is a kind of the base: a Car is a Vehicle. A Car has an Engine, so the engine should be a member, not a base class (composition).
Syntax
class Base {
protected:
int shared;
public:
Base(int s) : shared(s) {}
};
class Derived : public Base {
public:
Derived() : Base(5) {} // choose the base constructor
};
Example
#include <iostream>
using namespace std;
class Vehicle {
public:
int wheels;
Vehicle(int w) : wheels(w) {
cout << "Vehicle with " << wheels << " wheels" << endl;
}
~Vehicle() {
cout << "~Vehicle" << endl;
}
};
class Car : public Vehicle {
public:
Car() : Vehicle(4) {
cout << "Car" << endl;
}
~Car() {
cout << "~Car" << endl;
}
};
int main() {
Car c;
cout << c.wheels << " wheels" << endl;
return 0;
}Building a derived object runs the base constructor first, then the derived one: the base part must exist before the derived part builds on it. The derived constructor chooses which base constructor runs with : Base(args) in its initializer list. Destruction runs in reverse: derived first, then base. Watch the frames: Car::Car calls Vehicle::Vehicle before its own body runs.
Line by line
Vehiclehas a publicwheelsmember, and its constructor and destructor each print a line.Carderives fromVehiclewith: public Vehicle.Car()passes 4 to the base constructor with: Vehicle(4), soVehicle with 4 wheelsis printed beforeCar.c.wheelsworks, because the public base member is part of everyCar.- When
mainends,~Carruns first and then~Vehicle, the reverse of construction.
Expected result
Vehicle with 4 wheels
Car
4 wheels
~Car
~Vehicle
In the real world
GUI toolkits derive every button, text box and window from a common widget class. Game engines often derive game objects from a shared base that holds a position, so every object can be moved and drawn the same way.
Common mistakes
- Writing
class Dog : Animal: for aclass, inheritance is private by default, andrex.eat()frommainis refused. Write: public Animal. - Trying to use the base class's private members in the derived class: make them protected, or use public member functions.
- Expecting a base-class pointer to call the derived version of a function: that needs
virtual(next lesson).
Best practices
- Use public inheritance only when the derived class truly is a kind of the base.
- Keep data private where possible, and give derived classes protected functions instead.
- Keep hierarchies shallow, since deep ones are hard to change.
Summary
Inheritance lets a derived class reuse and extend a base class. The base part is built first and destroyed last, protected members are open to derived classes, and inheritance should model "is a", while "has a" uses a member.
Quick check
Key takeaways
- A derived object contains a base part.
- The base part is built first and destroyed last.
- Inherit only for "is a"; use a member for "has a".
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.