Effective C++条款36:继承与面向对象——绝不重新定义继承而来的non-virtual函数

一、看一个隐藏non-virtual函数的例子

  • 假设class D以public的方式继承于class B,代码如下:
class B {

public:

    void mf();

};

class D :public B {};


int main()
{
    D x;

    B *pB = &x;

    pB->mf(); //调用B::mf()

    D *pD = &x;

    pD->mf(); //调用D::mf()

    return 0;
}

二、静态绑定与动态绑定

静态绑定

  • 当我们调用non-virtual函数时,调用的函数版本与指针的类型有关
  • 例如,上面的pB指针在初始化时,将与D对象中的B对象所绑定;上面的pD指针在初始化时,将与D对象所绑定。这是静态绑定
  • 因此,pB调用的是B::mf();pD调用的是D::mf()

动态绑定

  • 当我们调用virtual函数时,调用的函数版本与指针所指的对象有关
  • 对virtual函数的调用,是在代码运行期间执行的。例如,如果上面的D::mf()是一个虚函数,那么会有:
class B {

public:

    virtual void mf();

};

class D :public B {

public:

    virtual void mf();

};


int main()

{
    D x;

    B *pB = &x;

    pB->mf(); //调用D::mf()

    
    D *pD = &x;
    
    pD->mf(); //调用D::mf()

    return 0;

}

 

三、为什么不建议派生类隐藏基类的non-virtual函数

  • 在条款32介绍过,public继承意味着is-a关系,条款34描述了为什么在class内声明一个non-virtual函数会为该class建立起一个不变性,凌驾其特异性。如果:
    • 我们在派生类中隐藏了基类的non-virtual函数,那么基类与派生类就会产生行为上的不一致,is-a关系就消失了
    • 如果想要表现出派生类与基类的不同,那么应该将函数声明为virtual(其中虚析构函数是一个例子)

四、总结

  • 绝对不要重新定义继承而来的non-virtual函数
上一篇:SyntaxError: Non-UTF-8 code starting with ‘\xc4‘ in file E:/7.python/day3/easyguis.py on line 2


下一篇:665. Non-decreasing Array