Effective C++ item 39: Use Private Inheritance Judiciously

The rule of thumb is, never use private inheritance unless you absolutely have to, and you almost never have to. Let’s see why.

Private inheritance is completely different than public inheritance, in many aspect. One is how compiler treat those differently.

1
2
3
4
5
6
7
8
9
class Person { ... };
class Student: private Person { ... };
void eat(const Person& p) { ... }
void study(const Student& s) { ... }

Person p;
Student s;
eat(p); // fine, p is a Person
eat(s); // error! a Student isn't a Person

In contrast to public inheritance, compilers will generally not convert a derived class object (such as Student) into a base class object (such as Person) if the inheritance relationship between the classes is private. That’s why the call to eat fails for the object s.

Private inheritance means is-implemented-in-terms-of. If you make a class D privately inherit from a class B, you do so because you are interested in taking advantage of some of the features available in class B, not because there is any conceptual relationship between objects of types B and D. As such, private inheritance is purely an implementation technique. Private inheritance means nothing during software design, only during software implementation.

So what’s the situation private inheritance is suitable? Let’s see and example. In this example, we want to write a Timer for our Widget class, and we find a Timer we can reuse all interfaces but need to change one function onTick. One way is to let Widget inherit from Timer privately, and redefine the virtual function onTick.

1
2
3
4
5
6
7
8
9
10
11
12
class Timer {
public:
...
virtual void onTick() const;
...
};
class Widget: private Timer {
private:
...
virtual void onTick() const; // implement widget specific ticking logic
...
};

An alternative, is to create a public inheritance WidgetTimer and use it as composition.

1
2
3
4
5
6
7
8
9
10
11
class WidgetTimer: public Timer {
public:
virtual void onTick() const;
...
};
class Widget {
...
private:
WidgetTimer timer;
...
};

So why public inheritance plus composition is preferred over private inheritance? Here are two reasons.

  1. You might want to design Widget to allow for derived classes, but you might also want to prevent derived classes from redefining onTick. If Widget inherits from Timer, that’s not possible, not even if the inheritance is private.
  2. You might want to minimize Widget‘s compilation dependencies. If Widget inherits from Timer, Timer‘s definition must be available when Widget is compiled, so the file defining Widget probably has to #include "Timer.h".

Private inheritance is most likely to be a legitimate design strategy when you’re dealing with two classes not related by is-a where one either needs access to the protected members of another or needs to redefine one or more of its virtual functions. Even in that case, we’ve seen that a mixture of public inheritance and containment can often yield the behavior you want, albeit with greater design complexity. Using private inheritance judiciously means employing it when, having considered all the alternatives, it’s the best way to express the relationship between two classes in your software.

Reference:
“Effective C++” Third Edition by Scott Meyers.