Effective C++:条款36:绝不重新定义继承而来的non-virtual函数

(一)首先有下面的继承体系:

class B { 
public: 
    void mf(); 
    ... 
}; 
class D : public B {...};

D x;

以下行为:

B* pB = &x;

pB->mf();

异于以下行为:

D* pD = &x;

pD->mf();

上面两种行为产生的结果不一定相同。看下面这种情况:

mf是个non-virtual函数而D定义有自己的mf版本:

class D : public B { 
public: 
    void mf(); 
    ... 
}; 
pB->mf();//调用B::mf 
pD->mf();//调用D::mf

对于同一个对象d,使用不同类型的指针指向它时,他表现得不尽相同。同理对于引用也是一样。


(二)上述现象的原因:

(1)造成这一行为的原因是,non-virtual函数都是静态绑定的。由于pB被声明为一个pointer-to-B,通过pB调用的non-virtual函数永远是B所定义的版本,即使pB指向一个类型为“B派生之Class”的对象。
(2)virtual函数是动态绑定的,如果mf是个virtual函数,不论通过pB还是通过pD调用mf,都会导致调用D::mf,因为pB和pD真正指的都是D的对象。


(三)

条款7“为多态基类声明虚析构函数”是本条款要求的特例:派生类可能有更多的成员变量和相应操作,因而析构函数必须与基类不同,采用虚析构函数的方法可以使用“动态绑定”从而产生安全的析构行为;反之,如果声明为非虚析构函数,必须重新定义,这和本条款的要求相违背。


请记住:

(1)绝对不要重新定义继承而来的 non-virtual 函数。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值