条款32:确定你的public继承保证了is-a关系
public继承的意思是:子类是一种特殊的父类,这就是所谓的“is-a”关系(适用于基类身上的每一件事情一定也适用于继承类身上)。但是本条款指出了其更深层次的意义:在使用public继承时,子类必须涵盖父类的所有特点,必须无条件继承父类的所有特性和接口(因为我们可以认为每一个派生类对象也都是一个基类对象)。之所以单独指出这一点,是因为如果单纯偏信生活经验,会犯错误。
比如鸵鸟是不是鸟这个问题,如果我们考虑飞行这一特性(或接口),那么鸵鸟类在继承中就绝对不能用public继承鸟类,因为鸵鸟不会飞,我们要在编译阶段消除调用飞行接口的可能性;但如果我们关心的接口是下蛋的话,按照我们的法则,鸵鸟类就可以public继承鸟类。同样的道理,面对矩形和正方形,生活经验告诉我们正方形是特殊的矩形,但这并不意味着在代码中二者可以存在public的继承关系,矩形具有长和宽两个变量,但正方形无法拥有这两个变量——没有语法层面可以保证二者永远相等,那就不要用public继承。
所以在确定是否需要public继承的时候,我们首先要搞清楚子类是否必须拥有父类每一个特性,如果不是,则无论生活经验是什么,都不能视作”is-a”的关系。public继承关系不会使父类的特性或接口在子类中退化,只会使其扩充。
条款 33:避免遮掩继承而来的名称
之前我们了解过 C++ 名称查找法则,这在继承体系中也是类似的,当我们在派生类中使用到一个名字时,编译器会优先查找派生类覆盖的作用域,如果没找到,再去查找基类的作用域,最后再查找全局作用域。名称遮盖问题——名称在作用域级别的遮盖是和参数类型以及是否虚函数无关的,即使子类重载了父类的一个同名,父类的所有同名函数在子类中都被遮盖。
考虑以下情形: