C++多态原理

C++的多态性是通过动态绑定实现的

  • 非虚函数是在编译时绑定的;
  • 通过对象进行的函数(虚函数,非虚函数)也是编译时绑定的;

C++编译器在编译的时候,要确定每个对象调用的函数(要求此函数是非虚函数)的地址,这称为早期绑定(early binding)

  • 当且仅当通过指针或引用调用虚函数时,动态绑定

动态绑定又叫运行时绑定(run time binding)。

example:

class animal{  
public:  
    void sleep(){  cout<<"animal sleep"<<endl;  }  
    void breathe(){  cout<<"animal breathe"<<endl;  }  
};  

class fish:public animal{
public:  
    void breathe(){  cout<<"fish bubble"<<endl;  }  
};  

int main(){  
    fish fh;  
    animal *pAn=&fh; // 隐式类型转换
    pAn->breathe();  // 运行结果: animal breathe
    return 0;
}  

因为编译器在编译的时候,就已经确定了对象调用的函数的地址
pAn->breathe()的函数地址为animal::breathe()的地址。

动态绑定

要解决这个问题就要使用动态绑定技术(有的地方叫迟绑定(late binding)技术)。(c++是静态绑定语言,一些动态绑定语言 如java ,python)

C++的多态性用一句话概括就是:

  1. 在基类的函数前加上virtual关键字,
  2. 在派生类中重写该函数,
  3. 运行时将会根据对象的实际类型来调用相应的函数。

编译器在编译的时候,发现animal类中有虚函数,此时编译器会为每个包含虚函数的类创建一个虚表(即vtable),
该表是一个一维数组,在这个数组 中存放每个虚函数的地址。
对于例例子,animal和fish类都包含了一个虚函数breathe(),因此编译器会为这两个类都建立一个虚表。

那么如何定位虚表呢?
编译器另外还为每个类的对象提供了一个虚函数表指针(即vptr),这个指针指向了对象所属类的虚函数表。
在程序运行时,根据对象的类型初始化vptr,从而让vptr正确的指向所属类的虚表,从而在调用虚函数时,就能够找到正确的函数。


简而言之,多态性是一个接口多种实现。

原文地址:https://www.cnblogs.com/iois/p/4979230.html