C++的动态绑定和静态绑定,为何运行时才能确定动态类型?

1、对象的静态类型和动态类型 

  1. 对象的静态类型:对象在声明时采用的类型。是在编译期确定的。
  2. 对象的动态类型:目前所指对象的类型,是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。

     关于对象的静态类型和动态类型,看一个示例:

classB

{

};

classC:publicB

{

};

classD:publicB

{

};

D*pD=newD(); // pD的静态类型是它声明的类型D*,动态类型也是D*

B*pB=pD; // pB的静态类型是它声明的类型B*,动态类型是pB所指向的对象pD的类型D*

C*pC=newC();

pB=pC; // pB的动态类型是可以更改的,现在它的动态类型是C*

2、静态绑定和动态绑定 

  1. 静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
  2. 动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。
classB

{

voidDoSomething();

virtualvoidvfun();

};

classC:publicB

{

voidDoSomething(); // 首先说明一下,这个子类重新定义了父类的no-virtual函数,这是一个不好的设计,会导致名称遮掩;这里只是为了说明动态绑定和静态绑定才这样使用。

virtualvoidvfun();

};

classD:publicB

{

voidDoSomething();

virtualvoidvfun();

};

D*pD=newD();

B*pB=pD;
  • pD->DoSomething()和pB->DoSomething()调用的不是同一个函数,虽然pD和pB都指向同一个对象。因为函数DoSomething是一个no-virtual函数,它是静态绑定的,也就是编译器会在编译期根据对象的静态类型来选择函数。pD的静态类型是D*,那么编译器在处理pD->DoSomething()的时候会将它指向D::DoSomething()。同理,pB的静态类型是B*,那pB->DoSomething()调用的就是B::DoSomething()。
  • pD->vfun()和pB->vfun()调用的是同一个函数,因为vfun是一个虚函数,它动态绑定的,也就是说它绑定的是对象的动态类型,pB和pD虽然静态类型不同,但是他们同时指向一个对象,他们的动态类型是相同的,都是D*,所以,他们的调用的是同一个函数:D::vfun()。
  • 上面都是针对对象指针的情况,对于引用(reference)的情况同样适用。指针和引用的动态类型和静态类型可能会不一致,但是对象的动态类型和静态类型是一致的。

       D D;

       D.DoSomething()和D.vfun()永远调用的都是D::DoSomething()和D::vfun()。

  • 至于哪些是动态绑定,哪些是静态绑定,总结为一句话:只有虚函数才使用的是动态绑定,其他的全部是静态绑定

3、一个困惑

看完上述讲解你可能有一个疑惑,即:“我看程序代码时,可以看出实际将会调用的函数,为何编译器不能在编译时确定将要调用的函数

一个示例来解决你的困惑:

Object* obj; 
std::cin >> type; 

switch (type) 
{ 
    case PEOPLE: obj = new People; 
    break; 
    case MUSLIM: obj = new Sheep; 
    break; 
} 

obj->WhichFunc();

此时你还能看出将要调用哪个函数么?哈哈哈

 

参考:深入理解C++的动态绑定和静态绑定

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章