深剖基类和派生类的虚函数表

时间:2022-09-08 07:39:10

1、当派生类实现基类的虚函数时,基类中虚函数表和虚函数地址和派生类中虚函数表和虚函数地址不同;

当派生类不实现基类的虚函数时,基类中虚函数表和虚函数地址和派生类中虚函数表和虚函数的地址相同。

1、派生类重新实现虚函数。查看其虚函数表和虚函数表中虚函数的地址 

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class Base{  
  4.     public:   
  5.     virtual void fun()  
  6.     {  
  7.         cout<<"This is Base Class"<<endl;  
  8.     }  
  9. };  
  10. class Derived:public Base{  
  11.     public:  
  12.     void fun()  
  13.     {  
  14.         cout<<"This is Derived Class"<<endl;  
  15.     }  
  16. };  
  17. int main()  
  18. {  
  19.     Base B;  
  20.     Derived D;   
  21.     int **p=(int**)&B;  
  22.     cout<<"基类的虚函数表地址:"<<p[0]<<endl;  
  23.     cout<<"基类的虚函数表中虚函数的地址:0x"<<hex<<p[0][0]<<endl;  
  24.     p=(int**)&D;  
  25.     cout<<"派生类的虚函数表地址:"<<p[0]<<endl;  
  26.     cout<<"派生类的虚函数表中虚函数的地址:0x"<<hex<<p[0][0]<<endl;  
  27.       
  28.     return 0;  
  29. }  

输出结果:
基类的虚函数表地址:0x445060
基类的虚函数表中虚函数的地址:0x415390
派生类的虚函数表地址:0x445070
派生类的虚函数表中虚函数的地址:0x4153dc
可以看出,基类和派生类的虚函数表不同,虚函数的地址也不同。这个结果符合预期,因为派生类中重新实现了虚函数,基类肯定

有自己的虚函数表,虚函数的地址自然是重新实现的那个。

2、派生类不重新实现虚函数。查看其虚函数表和虚函数表中虚函数的地址 

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class Base{  
  4.     public:   
  5.     virtual void fun()  
  6.     {  
  7.         cout<<"This is Base Class"<<endl;  
  8.     }  
  9. };  
  10. class Derived:public Base{  
  11.       
  12. };  
  13. int main()  
  14. {  
  15.     Base B;  
  16.     Derived D;   
  17.     int **p=(int**)&B;  
  18.     cout<<"基类的虚函数表地址:"<<p[0]<<endl;  
  19.     cout<<"基类的虚函数表中虚函数的地址:0x"<<hex<<p[0][0]<<endl;  
  20.     p=(int**)&D;  
  21.     cout<<"派生类的虚函数表地址:"<<p[0]<<endl;  
  22.     cout<<"派生类的虚函数表中虚函数的地址:0x"<<hex<<p[0][0]<<endl;  
  23.       
  24.     return 0;  
  25. }  
  26. 输出结果: 
基类的虚函数表地址:0x445050
基类的虚函数表中虚函数的地址:0x415390
派生类的虚函数表地址:0x445060
派生类的虚函数表中虚函数的地址:0x415390

派生类虽然重新实现虚函数,但是派生类有自己的虚函数表,但是虚函数表中,虚函数的地址和基类中虚函数的地址一样。 

3、一个类继承多个基类时,有一张虚函数表,多个虚函数指针。