考虑如下代码:
class B {
public:
void mf();
...
};
class D : public B {...};
面对一个类型为D的对象:
D x;
如果有以下行为:
B* pb = &x;
pb->mf();
异于以下行为:
D* pd = &x;
pD->mf();
如果mf是个non-virtual函数而D定义有自己的mf版本,那就会发生上述情况:
class D : public B {
public:
void md();
...
};
pb->mf(); // B::mf
pd->mf(); // D::mf
造成此行为的原因是,non-virtual函数都是静态绑定。由于pb被声明为B指针,通过pb调用的non-virtual函数永远是B的版本。
条款32说过,public继承意味着is-a的关系。条款34描述为什么在class内声明一个non-virtual函数会为该class建立一个不变性,凌驾其特异性。将这两个观点施行于两个class B和D和non-virtual成员函数mf上,那么:
- 适用于B对象的每一件事,也适用于D对象,因为每个D对象都是一个B对象。
- B的派生类一定会继承mf的接口和实现,因为mf是B的non-virtual函数。
现在,如果D重新定义mf,你的设计便会出现矛盾。任何情况下都不该重新定义一个继承而来的non-virtual函数。
请记住
- 绝对不要重新定义继承而来的non-virtual函数。