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 函数。



Effective C++:条款36:绝不重新定义继承而来的non-virtual函数,布布扣,bubuko.com

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

上一篇:Python 基础学习 网络小爬虫


下一篇:DFA最小化 -- Hopcroft算法 Python实现