您的位置:首页 > 其它

Item 36:不要重写继承来的非虚函数

2015-09-28 11:35 375 查看
Item 36: Never redefine an inherited non-virtual function.

我们还是在讨论public继承,比如
Derived
继承自
Base
。如果
Base
有一个非虚函数
func
,那么客户会倾向认为下面两种调用结果是一样的:

Derived d;
Base* pb = &d;
Derived* pd = &d;
// 以下两种调用应当等效
pb->func();
pd->func();


为什么要一样呢?因为public继承表示着"is-a"的关系,每个
Derived
对象都是一个
Base
对象(见Item
32)。

然而重写(override)非虚函数
func
将会造成上述调用结果不一致:

class Base{
public:
    void func(){}
};
class Derived: public Base{
public:
    void func(){}   // 隐藏了父类的名称func,见Item 33
};


因为
pb
类型是
Base*
pd
类型是
Derived*
,对于普通函数
func
的调用是静态绑定的(在编译期便决定了调用地址偏移量)。
总是会调用指针类型定义中的那个方法。即
pb->func()
调用的是
Base::func
pd->func()
调用的是
Derived::func


当然虚函数不存在这个问题,它是一种动态绑定的机制。

在子类中重写父类的非虚函数在设计上是矛盾的:

一方面,父类定义了普通函数
func
,意味着它反映了父类的不变式。子类重写后父类的不变式不再成立,因而子类和父类不再是"is
a"的关系。
另一方面,如果
func
应当在子类中提供不同的实现,那么它就不再反映父类的不变式。它就应该声明为
virtual
函数。

除非注明,本博客文章均为原创,转载请以链接形式标明本文地址: http://harttle.com/2015/09/03/effective-cpp-36.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: