32.确定你的public继承塑模出is-a关系
public继承主张,能够施行于base class对象身上的每件事情,也可以施行于derived class身上。
33.避免遮掩继承而来的名称
编译器必须实践的名称查找规则:
void Derived::mf4()
{
...
mf2();
...
}
当编译器看到这里使用名称mf2,必须估算它指涉的是什么东西。
首先查找local作用域,若是没有查找到(也就是mf4这个函数的作用域)
那就开始搜索外围作用域,也就是class Derived覆盖的作用域,若是还没有
开始在base class查找,找到了就停止,若是没有找到
找内含Base的namespace(s)的作用域(如果有的话)
最后向global作用域找去
子类内的名称会掩盖base classes内的名称,在public继承下从来没有人希望如此。
为了让被掩盖的名称再见天日,可使用using声明式或转交函数。
using使用方式:
using Base::mf1;//这样Base class内所有名为mf1的函数就都可以用了。
转交函数使用方式:
virtual void mf1()//只需要一个缺省的Base函数的时候可以这样做
{
Base::mf1();
}
34.区分接口继承和实现继承
表面上直截了当的public继承概念,经过更严密的检查之后,发现它由两部分组成:函数接口继承和函数实现继承。
纯虚函数的目的是为了让derived classes只继承函数接口。
virtual void draw() const = 0;
声明简朴的(非纯)impure virtual函数的目的,是让derived classes继承该函数的接口和缺省实现。
class Shape
{
public:
virtual void error(const std::string& msg);
}
相当于告诉子类,你必须支持一个error函数,但是如果你不想写一个也可以使用Shape class提供的缺省版本。
non-virtual函数具体指定接口继承以及强制性实现继承。
代表的意义是不变性和凌驾特异性,所以他不应该在derived class中被重新定义。
35.考虑virtual函数以外的其他选择
(我觉得。。。virtual挺好的)
36.绝不重新定义继承而来的non-virtual函数
37.绝不重新定义继承而来的缺省参数值i
virtual函数系动态绑定(你唯一需要去覆写的东西)
缺省参数值是静态绑定
38.通过复合塑模出has-a或"根据某物实现出"
复合就是一个类型中含有其他类型对象,这并不是public继承,他们的意义完全不同。
在应用域复合意味着has-a,在实现域,复合意味着is-implemented-in-terms-of(根据某物实现出)
39.明智而审慎的使用private继承
他的含义也是根据某物实现出,但是复合的优先级要高于private继承
40.明智而审慎的使用多重继承
对于virtual base classes(也相当于对virtual继承)的忠告:
(1)非必要不使用virtual bases,平常请使用non-virtual继承。
(2)如果你必须使用virtual base classes,尽可能避免在其中防止数据。
virtual会增加大小速度,初始化及赋值复杂度等等成本,如果virtual base class不带任何数据,将是最具实用价值的情况。