Effective C++: Item 39 -- Use private inheritance judiciously

注: 此为英文资料整理,如需翻译请私信或留评论


Private inheritance doesn’t mean is-a. In contrast to public inheritance, compilers will generally not convert a derived class object into a base class object if the inheritance relationship between the classes is private.


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); // not ok, s is not a person

So how does private inheritance behave?

Members inherited from a private base class become private members of the derived class, even if they were protected or public in the base class. Thus, private inheritance means is-implemented-in-terms-of. It is used purely as an implementation technique. Private inheritance means nothing during software design, only during software implementation.

How do we choose between private inheritance and composition?

Use composition whenever you can, only use private inheritance when necessary.

When is necessary?

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


Suppose we’re working on an application involving Widgets, and we decide we need to better understand how Widgets are being used. We decide to modify the Widget class to keep track of how many times each member function is called by reusing the existing Timer class.

class Timer { 
	explicit Timer(int tickFrequency); 
	virtual void onTick() const; // automatically called for each tick

We cannot use public inheritance since Widgets is not a Timer. Thus, we use private inheritance.

class Widget: private Timer { 
	virtual void onTick() const;

By virtue of private inheritance, Timer’s public onTick function becomes private in Widget, and we keep it there when we redeclare it.

Yet another way of solving this question using composition

We’d just declare a private nested class inside Widget that would publicly inherit from Timer, redefine onTick there, and put an object of that type inside Widget.

class Widget { 
	class WidgetTimer: public Timer {
		virtual void onTick() const;
	WidgetTimer timer;

Two reason to use this method over the private inheritance:

  1. Design Widget to allow for derived classes, but prevent derived classes from redefining onTick.
    Derived classes may redefine virtual functions even if they are not permitted to call them.
  2. 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.
    On the other hand, if WidgetTimer is moved out of Widget and Widget contains only a pointer to a WidgetTimer, Widget can get by with a simple declaration for the WidgetTimer class; it need not #include anything to do with Timer

2. When space concerns can tip the scales toward private inheritance.

EBO – Empty Base Optimization

Empty class: Such classes have no non-static data members; no virtual functions (because the existence of such func- tions adds a vptr to each object); and no virtual base classes (because such base classes also incur a size overhead)

class Empty {}; // has no data, so objects should // use no memory
class HoldsAnInt {  
	int x; 
	Empty e; // should need only space for an int // should require no memory

However, sizeof(HoldsAnInt) > sizeof(int) because C++’s edict against zero-size freestanding objects is typically satisfied by the silent insertion of a char into “empty” objects.
This constraint doesn’t apply to base class parts of derived class objects, because they’re not freestanding.

class HoldsAnInt: private Empty { 
	int x; 

You’re almost sure to find that sizeof(HoldsAnInt) == sizeof(int). This is known as the empty base optimization (EBO)

Things to Remember

  • Private inheritance means is-implemented-in-terms of. It’s usually inferior to composition, but it makes sense when a derived class needs access to protected base class members or needs to redefine inherited virtual functions.
  • Unlike composition, private inheritance can enable the empty base optimization. This can be important for library developers who strive to minimize object sizes.
  • 0
  • 0
  • 打赏
  • 0


  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页




¥2 ¥4 ¥6 ¥10 ¥20
余额支付 (余额:-- )



钱包余额 0