Effective C++第39条:使用private继承

2021/02 22 22:02

1、private继承的两条规则

  • 规则一:如果classes之间是private继承关系,那么编译器不会自动将一个derived class对象转换为一个base class对象。
  • 规则二:由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原本是protected 或public属性。

2、private 继承所描述的关系

  • private继承 意味这implemented-in-terms-of 。private 继承只是一种实现技术,它没有“设计”层面上的意义。
  • private继承只有实现部分被继承,接口应该被忽略。

3、复合与private继承的选择

疑问:

复合和private继承都是描述implemented-in-terms-of 关系,那么在类设计时应该使用复合还是private继承该如何选择呢?

(1)首先大部分情况下应该尽可能的使用复合。
(2)在下述几种情况使用private继承:
  • 当protected成员或virtual函数牵扯进来的时候。(由于需求的原因,这时正统的设计)
  • 另一种更激进的情况:当基类为空类时,可以起到节约内存空间的作用。(如果客户对于内存空间的要求极高的话,可以采用private继承。)

注意:“empty class”:这里的空类是指只包含:typedefs,enums,static成员变量或者non-virtual函数,不包含non-static成员。

4、复合与private继承的优缺点比较

  • 复合要比private继承复杂一些。
  • 复合比private继承更容易理解。
  • 复合的耦合性(依存性,需要包含头文件,需要注意文件加载顺序等问题。)要比private继承低。这对大型程序设计非常重要。
  • private继承在某些对内存要求比较高的场合可以起到节约内存的作用。
  • 学习private继承的另一目的是扩展解决问题的思路。

5、private继承是如何做到节约内存空间的?

如果一个类为 空类的话,按道理讲,它是不会占用内存空间的。但是如果设计成组合关系,那么编译器会为空类分配一个字节char的内存空间(此时,sizeof(派生类 x) >sizeof(派生类成员变量)),而又由于对齐需求,可能这个字节最终甚至会变成一个int大小。

如果设计成private继承的话,可以避免上述情况。即:sizeof(派生类 x) == sizeof(派生类成员变量),这便是所谓的EBO(空白基类最优化)。

注意:

  • 一个独立对象的大小一定不为0,但是这个约束不适用于派生类对象内的base class成分,因为这部分并非是独立的。
  • 在STL中,EBO技术应用很广泛。其base class往往是含有typedefs 的基类。例如:base classes unary_funtion 和binary_funtion,这些是用户自定义函数对象通常要继承的基类。