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

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.land/2015/09/03/effective-cpp-36.html
感谢作者 Harttle

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值