浅谈c++虚函数 虚继承的虚表剖析

来源:互联网 发布:织梦cms文档权限 编辑:程序博客网 时间:2024/06/09 00:06

 1 虚函数的虚表剖析

  (1)没有覆盖公有继承 派生类的虚表

class CBase //没有覆盖{public:virtual void FunTest0(){ cout << "CBase::FunTest0()"; }virtual void FunTest1(){ cout << "CBase::FunTest1()"; }virtual void FunTest2(){ cout << "CBase::FunTest2()"; }public:int data1;};class CDerived :public CBase{public:virtual void FunTest4(){ cout << "CDerived::FunTest4()"; }virtual void FunTest5(){ cout << "CDerived::FunTest5()"; }virtual void FunTest6(){ cout << "CDerived::FunTest6()"; }int data2;};typedef void(*FUN_TEST)(); //定义一个函数指针void PrintVF(){// 1种方法//for (int idx = 0; idx < 3;idx++)//{//FUN_TEST funTest = (FUN_TEST)(*((int*)*(int *)&b + idx));//// (int *)&b将b的地址值强转换成int*指针////*(int *)&b 将b的地址值取出来 0021fe04////(int*)*(int *)&b 将0021fe04 强转换成一个指针   +idx 指针里面的东西偏移idx单元////*((int*)*(int *)&b 将0021fe04 地址里面的值取出来//funTest();//cout << ": " << (int *)funTest << endl;//}CDerived d;d.data2 = 2;d.data1 = 1;cout << "CDerived的大小:" << sizeof(CDerived) << endl;cout << "CDerived vfptr:" << endl;FUN_TEST *funTest2 = (FUN_TEST*)(*(int*)&d);while (*funTest2){(*funTest2)();cout << ": " << *funTest2 << endl;funTest2++;}}
  剖析 虚表

   

  说明:虚函数按声明顺序存在于虚表中;

             在派生类中,前面是基类的虚函数,后面是派生类的虚函数

(2)有覆盖 的公有继承派生类的虚表

   

class CBase{public:CBase():data1(1){}virtual void FunTest0(){ cout << "CBase::FunTest0()" ; }virtual void FunTest1(){ cout << "CBase::FunTest1()" ; }virtual void FunTest2(){ cout << "CBase::FunTest2()" ; }virtual void FunTest3(){ cout << "CBase::FunTest3()" ; }int data1;};class CDerived :public CBase{public:CDerived():data2(2){}virtual void FunTest0(){ cout << "CDerived::FunTest0()" ; } //重写virtual void FunTest1(){ cout << "CDerived::FunTest1()" ; }//重写virtual void FunTest4(){ cout << "CDerived::FunTest4()" ; }virtual void FunTest5(){ cout << "CDerived::FunTest5()" ; }int data2;};typedef void(*_pFunTest)();void PrintVF() //打印虚表{CDerived derived;derived.data1 = 1;derived.data2 = 2;cout << "CDerived vfptr:" << endl;_pFunTest* pFunTest2 = (_pFunTest*)(*(int *)&derived);while (*pFunTest2){(*pFunTest2)();cout << ": " << *pFunTest2 << endl;pFunTest2++;}}void TestVirtual() // 测试调用基类还是派生类的虚表{CBase base;CDerived derived;CBase* PBase1 = &base; // 基类的指针指向基类,获取到的是基类的虚表PBase1->FunTest0(); //调用基类的FunTest0cout << endl;CBase* PBase2 = &derived;//基类的指针指向派生类,获取到的是派生类的虚表PBase2->FunTest0();  //掉用派生类FunTest0}
 虚表剖析

 

    派生类虚表的形成: a.先拷贝基类的虚表 

     b.如果派生类重写了基类的虚函数,则修改同位置的基类虚函数

     c.跟上派生类新定义的虚函数

   调用虚表:通过基类的引用或指针调用虚函数时,调用基类还是派生类的虚函数,

     要根据运行时引用或指针的实际指向的类型确定。

    单继承的派生类的大小:虚表+ 基类的数据成员 + 派生类的成员

  2 多继承

  

class Base1  //有覆盖{public:Base1():_data1(1){}virtual void Test1(){cout << "Base::Test1()";}virtual void Test2(){cout << "Base::Test2()";}virtual void Test3(){cout << "Base::Test3()";}int _data1;};class Base2{public:Base2():_data2(2){}virtual void Test4(){cout << "Base::Test4()" ;}virtual void Test5(){cout << "Base::Test5()" ;}virtual void Test6(){cout << "Base::Test6()" ;}int _data2;};class Derived :public Base1, public Base2{public:Derived():_data3(3){}virtual void Test1(){cout << "Derived::Test1()" ;}virtual void Test5(){cout << "Derived::Test5()" ;}virtual void Test7()  //添加到Base1的虚表中{cout << "Derived::Test7()" ;}int _data3;};typedef void(*VFP)();void PrintVfp(){Derived d;d._data1 = 1;d._data2 = 2;d._data3 = 3;VFP* vfp = (VFP*)*(int *)&d;cout << "Derived vir table:" << endl;while (*vfp){(*vfp)();cout <<": "<< *vfp << endl;++vfp;}cout << endl;Base1& b1 = d;VFP* vfp1 = (VFP*)*(int *)&b1;cout << "Base1 vir table:" << endl;while (*vfp1){(*vfp1)();cout << ": " << *vfp1 << endl;++vfp1;}cout << endl;Base2& b2 = d;VFP* vfp2 = (VFP*)*(int *)&b2;cout << "Base2 vir table:" << endl;while (*vfp2){(*vfp2)();cout << ": " << *vfp2 << endl;++vfp2;}cout << endl;}
  数据模型:                                              虚表剖析:                                                                                                                

   

  

   (3)菱形继承

    

class Base{public:Base(){}virtual void Test1(){cout << "Base::Test1()";}int data1;};class C1 :public Base{public:virtual void Test1(){cout << "C1::Test1()";}virtual void Test2(){cout << "C1::Test2()";}int data2;};class C2 :public Base{public:virtual void Test1(){cout << "C2::Test1()";}virtual void Test3(){cout << "C2::Test3()";}int data3;};class D :public C1, public C2{public:virtual void Test1(){cout << "D::Test1()" ;}virtual void Test2(){cout << "D::Test2()" ;}virtual void Test3(){cout << "D::Test3()";}virtual void Test4(){cout << "D::Test4()";}int data4;};typedef void(*VFP)();void PrintVFP(){D d;d.C1::data1 = 0;d.C2::data1 = 1;d.data2 = 2;d.data3 = 3;d.data4 = 4;C1& c1 = d;VFP* vfp1 = (VFP*)*(int *)&c1;cout << "C1 vir table:" << endl;while (*vfp1){(*vfp1)();cout <<" : " <<*vfp1 << endl;++vfp1;}cout << endl;C2& c2 = d;VFP* vfp2 = (VFP*)*(int *)&c2;cout << "C2 vir table:" << endl;while (*vfp2){(*vfp2)();cout << " : " << *vfp2 << endl;++vfp2;}cout << endl;}
 虚表剖析:                                                                                                          数据模型:

         

      说明: 如果派生类D有新的虚函数,则添加到第一继承顺序的基类c1的虚表后面

                  该菱形继承存在二义性,c1和c2中都继承了base的成员变量

     菱形继承的大小:28   c1(虚表指针+base成员+c1成员 12) + c2(12) + 派生类D的成员

 2 虚继承

   (1)单继承

     

class Base{public:Base():data1(33){}virtual void Test1(){cout << "Base::Test1()";}virtual void Test2(){cout << "Base::Test2()";}virtual void Test3(){cout << "Base::Test3()";}int data1;};class Derived :virtual public Base{public:Derived() // 1填写偏移量表格地址 2调用基类构造函数(填写基类虚表地址) 3填写派生类虚表地址      //4 重新填写属于基类对象部分的虚表地址(用派生类的虚表) 5派生类对象和基类对象之间用0分割(虚拟继承中有构造或析构才会用0){}~Derived(){}virtual void Test1(){cout << "Derived::Test1()";}virtual void Test3(){cout << "Derived::Test3()" ;}virtual void Test4() // 屏蔽掉 大小为16  没有第一个虚表{cout << "Derived::Test4()";}int data2;};void TestSize(){Derived d;d.data1 = 1;d.data2 = 2;cout << sizeof(Derived) << endl;  // 24 去掉析构函数和构造函数 20 多加四个字节}typedef void(*VFP)();void PrintVfp(){Derived d;d.data1 = 1;d.data2 = 2;VFP* vfp = (VFP*)*(int *)&d;cout << "Derived vir table  1:" << endl;while (*vfp){(*vfp)();cout << ": " << *vfp << endl;++vfp;}cout << endl;Base& b = d;VFP* vfp1 = (VFP*)*(int *)&b;cout << "Derived vir table: 2 Base" << endl;while (*vfp1){(*vfp1)();cout << ": " << *vfp1 << endl;++vfp1;}cout << endl;}
   虚表剖析:

   a  没有构造函数和析构函数(少中间的0 四个字节),派生类有新的虚函数
   
    b 没有构造函数和构造函数(少中间的0 四个字节)   c。有构造函数或者析构函数

       派生类没有新的虚函数                                                     派生类新定义了虚函数

                                         

    简述一下构造函数的作用:(派生类的构造函数做了什么)

     

    

(2)多继承

     没有考虑构造函数或析构函数 ,派生类定义了新虚函数

class C1{public:virtual void Test1(){cout << "C1::Test1()";}virtual void Test2(){cout << "C1::Test2()";}int data1;};class C2{public:virtual void Test3(){cout << "C2::Test3()";}virtual void Test4(){cout << "C2::Test4()";}int data2;};class D :public virtual C1, public virtual C2{public:virtual void Test1() //重写c1的Test1{cout << "D::Test1()";}virtual void Test3() //重写c2的Test3{cout << "D::Test3()";}virtual void Test5() //派生类特有的Test5{cout << "D::Test5()";}int data3;};typedef void(*VFP)();void PrintVfp(){D d;d.data3 = 3;d.data2 = 2;d.data1 = 1;VFP* vfp3 = (VFP*)*(int *)&d;cout << " 派生类自己特有的虚表:" << endl;while (*vfp3){(*vfp3)();cout << ": " << *vfp3 << endl;++vfp3;}cout << endl;C1& c1 = d;VFP* vfp1 = (VFP*)*(int *)&c1;cout << " c1的虚表:" << endl;while (*vfp1){(*vfp1)();cout << ": " << *vfp1 << endl;++vfp1;}cout << endl;C2& c2 = d;VFP* vfp2 = (VFP*)*(int *)&c2;cout << " c2的虚表:" << endl;while (*vfp2){(*vfp2)();cout << ": " << *vfp2 << endl;++vfp2;}cout << endl;}
  剖析虚表:

   

   (3)菱形虚拟继承,解决了二义性

        没有构造函数或析构函数,派生类类定义了新的虚函数

class Base{public:Base():_data1(0){}virtual void Test1(){cout << "Base::Test1()" ;}int _data1;};class C1 :virtual public Base{public:virtual void Test1(){cout << "C1::Test1()" ;}virtual void Test2(){cout << "C1::Test2()"  ;}int _data2;};class C2 :virtual public Base{public:virtual void Test1(){cout << "C2::Test1()" ;}virtual void Test3(){cout << "C2::Test3()" ;}int _data3;};class D :public C1, public C2{public:virtual void Test1(){cout << "D::Test1()" ;}virtual void Test2(){cout << "D::Test2()" ;}virtual void Test3(){cout << "D::Test3()" ;}virtual void Test4(){cout << "D::Test4()";}int _data4;};typedef void(*VFP)();void PrintVfp(){D d;d._data1 = 1;d._data2 = 2;d._data3 = 3;d._data4 = 4;C1& c1 = d;VFP* vfp1 = (VFP*)*(int *)&c1;cout << " vir table up:" << endl;while (*vfp1){(*vfp1)();cout << ": " << *vfp1 << endl;++vfp1;}cout << endl;C2& c2 = d;VFP* vfp2 = (VFP*)*(int *)&c2;cout << " vir table mid:" << endl;while (*vfp2){(*vfp2)();cout << ": " << *vfp2 << endl;++vfp2;}cout << endl;Base& b = d;VFP* vfp3 = (VFP*)*(int *)&b;cout << " vir table down:" << endl;while (*vfp3){(*vfp3)();cout << ": " << *vfp3 << endl;++vfp3;}cout << endl;}
  

  

     

3 0
原创粉丝点击