这个条款的内容很简单,见下面的示例:
1 class BaseClass 2 { 3 public: 4 void NonVirtualFunction() 5 { 6 cout << "BaseClass::NonVirtualFunction" << endl; 7 } 8 }; 9 10 class DerivedClass: public BaseClass 11 { 12 public: 13 void NonVirtualFunction() 14 { 15 cout << "DerivedClass::NonVirtualFunction" << endl; 16 } 17 }; 18 19 int main() 20 { 21 DerivedClass d; 22 BaseClass* bp = &d; 23 DerivedClass* dp = &d; 24 bp->NonVirtualFunction(); // 输出BaseClass::NonVirtualFunction 25 dp->NonVirtualFunction(); // 输出DerivedClass::NonVirtualFunction 26 }
从输出结果可以看到一个有趣的现象,那就是两者都是通过相同的对象d调用成员函数NonVirutalFunction,但显示结果却不相同,这会给读者带来困惑。
现在这个现象的原因是在于BaseClass:NonVirutalFunction与DerivedClass:NonVirtualFunction都是静态绑定,所以调用的non-virtual函数都是各自定义的版本。
回顾下之前的条款,如果是public继承的话,那么:
1) 适用于BaseClass的行为一定适用于DerivedClass,因为每一个DerivedClass对象都是一个BaseClass对象;
2) 如果BaseClass里面有非虚函数,那么DerivedClass一定是既继承了接口,也继承了实现;
3) 子类里面的同名函数会掩盖父类的同名函数,这是由于搜索法则导致的。
如果DerivedClass重定义一个non-virtual函数,那么会违反上面列出的法则。以第一条为例,如果子类真的要重定义这个函数,那么说明父类的这个函数不能满足子类的要求,这就与每一个子类都是父类的原则矛盾了。
可以总结一下了,无论哪一个观点,结论都相同:
任何情况下都不该重新定义一个继承而来的non-virtual函数。