C++中不应该为从基类继承的non-virtual函数重新定义
在C++中,派生类不应该对从基类继承的non-virtual函数重新定义,首先看下面一段代码:
1 class B 2 { 3 public: 4 void mf(); 5 ... 6 }; 7 8 class D:public B 9 { 10 ... 11 }; 12 13 D x; 14 B* pb = &x; 15 pb->mf(); 16 17 D* pd = &x; 18 pd->mf();
上面的代码中第15行和第18行调用的函数都是mf,且pb和pd都是指向对象D的,那么这两次调用是否是同一个函数呢?答案是不一定,因为如果D中重新定义了mf函数,那么15行调用的是B::mf(),而第18行则调用的是D::mf(),因为不同于virtual的动态绑定(导致的结果是调用的函数是指针指向的对象的函数,即两次都是调用D的mf函数),这里的non-virtual是静态绑定的,B和D中都有各自的mf版本,调用不决定于指针所指的对象,而是指针的类型。这便造成了D即派生类对象调用同一函数的行为不一致性,因为具体的行为不取决于D对象,而取决于指向D对象的指针类型。
此外,基于public继承是"is a"的关系,也不应该在派生类中重新定义non-virtual函数,这是因为对于non-virtual函数,派生类继承了接口和实现,因而如果重新定义实现,B就不是一个D了,违背了public继承的实质。
以上整理自Effective C++中文版第三版case 36.