C++静态绑定与动态绑定

开发日志系列(十一)

目前我参与的项目中使用了大量的接口调用,大量的继承(多重继承,多重派生等),其中的大部分都是使用了C++语言的动态绑定特性.既然有动态绑定,哪就相应的肯定有静态绑定,今晚复习了下这个特性.

静态绑定与动态绑定

静态绑定又名前期绑定(early binding),绑定的是对象的静态类型发生在编译期.动态绑定又名后期绑定(late binding),绑定的是对象的动态类型,发生在运行期.简单的说就是:静态绑定在编译完成后已经确定,动态绑定则需要在运行的时候才确定.考虑如下继承:

class B{
public:
    void testA(){printf("class B testA()\n");};
    virtual void testB(){printf("class B testB()\n");};
};

class D:public B{
public:
    void testA(){printf("class D testA()\n");};
    virtual void testB(){printf("class D testB()\n");};
};

int main(int argc, const char * argv[])
{

    // insert code here...
    
    D x;
    B* pB = &x;
    D* pD = &x;
    printf("testing non-virturl\n");
    pB->testA();
    pD->testA();
    printf("testing virturl\n");
    pB->testB();
    pD->testB();
    return 0;
}

运行后输出如下:

testing non-virturl
class B testA()
class D testA()
testing virturl
class D testB()
class D testB()

pB,pD虽然都指向派生类D,但是调用non-virtual函数(非虚成员函数)的时候pB调用到基类B的定义.调用virtual函数(虚函数)的时候则均是调用到派生类D的定义.

原因在于:

非虚函数属于静态绑定,所以类B或者D 指针调用非虚函数的时候 均是调用到自身的定义.

虚函数属于动态绑定,无论指针类型是基类B还是派生类D,调用到的都取决于调用的那个对象的类型.

往后C++编程中应当避免

  • 重新定义非虚成员类
  • 多重继承中的指针频繁转换
  • 接口基类不应该有非虚函数(也就是全部设置位纯虚函数)

这篇日志系Effective C++读书笔记,参考其中第36,37条款.

《C++静态绑定与动态绑定》有3个想法

高军进行回复 取消回复

邮箱地址不会被公开。 必填项已用*标注