• C++ 虚函数表 多重继承


            上次研究的是单继承的情况,这次研究多重继承下的虚函数表的排列情况。

            

             这次A,A1,A2,B这几个类的继承关系如下图:

             

                  测试代码如下:

    #include<iostream>
    using namespace std;
    
    class  A
    {
    public:
            virtual void fun1()
            {
                    cout<<"A::fun1"<<endl;
            }
            virtual void fun2()
            {
                    cout<<"A::fun2"<<endl;
            }
    
            virtual void fun3()
            {
                    cout<<"A::fun3"<<endl;
            }
    
    
    };
    
    
    class A1:public A
    {
    public:
            virtual void fun1()
            {
                    cout<<"A1::fun1"<<endl;
            }
    
    };
    
    
    class A2:public A
    {
    public:
            virtual void fun2()
            {
                    cout<<"A2::fun2"<<endl;
            }
            virtual void  fun3()
            {
                    cout<<"A2::fun3"<<endl;
            }
    };
    
    class B :public A1,public A2
    {
    public:
            virtual void fun4()
            {
                    cout<<"B::fun4"<<endl;
            }
    };
    
    typedef void (*Fun)(void);
    int main(int argc, char* argv[])
    {
            A1   a1;
    
            cout<<"A1虚函数表的地址为:"<<(int *)(&a1)<<endl;
    
            cout<<"A1第一个虚函数的地址为:"<<(int *) *(int *)(&a1)<<endl;
    
            Fun fun1,fun2,fun3,fun4;
    
            fun1=( Fun) ( *(int *) *(int *)(&a1));
            fun1();
    
    
            fun2=(Fun) (* ((int *) *(int *)(&a1)+1));
            fun2();
    
            fun3=(Fun) (* ((int *) *(int *)(&a1)+2));
            fun3();
    
    
            A2  a2;
    
            cout<<"A2虚函数表的地址为:"<<(int *)(&a2)<<endl;
            cout<<"A2第一个虚函数的地址为:"<<(int *) *(int *)(&a2)<<endl;
    
    
            fun1=( Fun) ( *(int *) *(int *)(&a2));
            fun1();
    
    
            fun2=(Fun) (* ((int *) *(int *)(&a2)+1));
            fun2();
    
            fun3=(Fun) (* ((int *) *(int *)(&a2)+2));
            fun3();
    
            B   b;
            cout<<"B的第一个虚函数表的地址为:"<<(int *)(&b)<<endl;
            cout<<"B的第一个虚函数表的第一个虚函数的地址为:"<<(int *) *(int *)(&b)<<endl;
    
    
            fun1=( Fun) ( *(int *) *(int *)(&b));
            fun1();
    
    
            fun2=(Fun) (* ((int *) *(int *)(&b)+1));
            fun2();
    
            fun3=(Fun) (* ((int *) *(int *)(&b)+2));
            fun3();
    
            fun4=(Fun) (* ((int *) *(int *)(&b)+3));
            fun4();
    
            cout<<"B的第二个虚函数表的地址为:"<<(int *)(&b)+1<<endl;
            cout<<"B的第二个虚函数表的第一个虚函数的地址为:"<<(int *) *((int *)(&b)+1)<<endl;
    
            fun1=( Fun) ( *(int *) *((int *)(&b)+1));
            fun1();
    
    
            fun2=(Fun) (* ((int *) *((int *)(&b)+1)+1));
            fun2();
    
            fun3=(Fun) (* ((int *) *((int *)(&b)+1)+2));
            fun3();
            return 0;
    }
    

    运行结果:

    A1虚函数表的地址为:0xbfb2e9ec
    A1第一个虚函数的地址为:0x8048ff0
    A1::fun1
    A::fun2
    A::fun3
    A2虚函数表的地址为:0xbfb2e9d8
    A2第一个虚函数的地址为:0x8048fd8
    A::fun1
    A2::fun2
    A2::fun3
    B的第一个虚函数表的地址为:0xbfb2e9d0
    B的第一个虚函数表的第一个虚函数的地址为:0x8048fa8
    A1::fun1
    A::fun2
    A::fun3
    B::fun4
    B的第二个虚函数表的地址为:0xbfb2e9d4
    B的第二个虚函数表的第一个虚函数的地址为:0x8048fc0
    A::fun1
    A2::fun2
    A2::fun3

                 具体说下B的情况,b分别从A1,A2继承了两个虚函数表,这两个虚函数表也是在对象的开始按照顺序开始排列,先是A1的虚函数表,然后是A2的虚函数表。


                  B的第一个虚函数表:(int *)(&b)

                  B的第一个虚函数表的第一个元素fun1=  * ((int *)  * (int *)(&b))

                  B的第一个虚函数表的第二个元素fun2=  * ((int *)  * (int *)(&b)+1)

                  ......

                  B的第二个虚函数表:(int *)(&b)+1

                  B的第二个虚函数表的第一个元素 fun1=   * ((int *) *((int *)(&b)+1)+0)

                  B的第二个虚函数表的第二个元素 fun2=  * ((int *) *((int *)(&b)+1)+1)

    结果画成虚函数表如下:

         A的虚函数表图:

         

         A1的虚函数表图:

         

         A2的虚函数表图:

         

        B的虚函数表图:

       

           

         结论:

         多重继承会有多个虚函数表,几重继承,就会有几个虚函数表。这些表按照派生的顺序依次排列,如果子类改写了父类的虚函数,那么就会用子类自己的虚函数覆盖虚函数表的相应的位置,如果子类有新的虚函数,那么就添加到第一个虚函数表的末尾。


    注意:这里由于类A1和A2都只有指向虚函数表的指针,所以对于类B而言,这两个指针连续。如果A1有个成员的为int类型,则B的第二个虚函数表:(int *)(&b)+2,例如:

    #include<iostream>
    using namespace std;
    
    class Base1
    {
      public:
        Base1(int num):num_1(num){}
        virtual void foo1() { cout << "Base1:: foo1" << num_1 << endl;}
        virtual void foo2() { cout << "Base1:: foo2" << num_1 << endl;}
        virtual void foo3() { cout << "Base1:: foo3" << num_1 << endl;}
      private:
        int num_1;
    };
    
    class Base2
    {
      public:
        Base2(int num):num_2(num){}
        virtual void foo1() { cout << "Base2:: foo1" << num_2 << endl;}
        virtual void foo2() { cout << "Base2:: foo2" << num_2 << endl;}
        virtual void foo3() { cout << "Base2:: foo3" << num_2 << endl;}
      private:
        int num_2;
    };
    
    class Base3
    {
      public:
        Base3(int num):num_3(num){}
        virtual void foo1() { cout << "Base3:: foo1" << num_3 << endl;}
        virtual void foo2() { cout << "Base3:: foo2" << num_3 << endl;}
        virtual void foo3() { cout << "Base3:: foo3" << num_3 << endl;}
      private:
        int num_3;
    };
    
    class Derived1:public Base1
    {
      public:
        Derived1(int num):Base1(num){}
        virtual void faa1(){ cout << "Dervied1::faa1" <<endl;}
        virtual void faa2() { cout << "Dervied1::faa2" <<endl;}
    };
    
    class Derived2:public Base1
    {
      public:
        Derived2(int num):Base1(num){}
        virtual void foo2(){ cout << "Dervied2::foo2" << endl;}
        virtual void fbb2(){ cout << "Dervied2::fbb2" << endl;}
        virtual void fbb3(){ cout << "Dervied2::fbb3" << endl;}
    };
    
    class Derived3:public Base1,public Base2,public Base3
    {
      public:
        Derived3(int num_1,int num_2,int num_3):
             Base1(num_1),Base2(num_2),Base3(num_3){}
        virtual void fcc1(){ cout << "Dervied3::fcc1" << endl;}
        virtual void fcc2(){ cout << "Dervied3::fcc2" << endl;}
    };
    
    class Dervied4:public Base1,public Base2,public Base3
    {
      public:
        Dervied4(int num_1,int num_2,int num_3):
             Base1(num_1),Base2(num_2),Base3(num_3){}
        virtual void foo1(){ cout << "Dervied4::foo1" << endl;}
        virtual void fdd(){ cout << "Dervied4::fdd" << endl;}
    };
    
    typedef void (*Fun)(void);
    int main()
    {
      Base1* pBase1 = NULL;
      Base2* pBase2 = NULL;
      Base3* pBase3 = NULL;
      Fun pFun;
    
    cout << "--------------------------------" << endl;
      Derived1 d1(1);
      pBase1 = &d1;
      pBase1->foo1();
    cout << "------------Derived1----------------" << endl;
      pFun = (Fun)*((int*)*(int*)(&d1)+0);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d1)+1);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d1)+2);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d1)+3);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d1)+4);
      pFun();
    
    cout << "--------------------------------" << endl;
      Derived2 d2(2);
      pBase1 = &d2;
      pBase1->foo2();
    cout << "------------Derived2----------------" << endl;
      pFun = (Fun)*((int*)*(int*)(&d2)+0);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d2)+1);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d2)+2);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d2)+3);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d2)+4);
      pFun();
    
    cout << "--------------------------------" << endl;
      Derived3 d3(1,2,3);
      pBase1 = &d3;
      pBase2 = &d3;
      pBase3 = &d3;
      pBase1->foo1();
      pBase2->foo1();
      pBase3->foo1();
    cout << "------------Derived3----------------" << endl;
      pFun = (Fun)*((int*)*(int*)(&d3)+0);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d3)+1);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d3)+2);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d3)+3);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d3)+4);
      pFun();
    
      pFun = (Fun)*((int*)*((int*)(&d3)+2)+0); // Base1 有一个int 类型的成员变量
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d3)+2)+1);
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d3)+2)+2);
      pFun();
    
      pFun = (Fun)*((int*)*((int*)(&d3)+4)+0); // Base2 有一个int 类型的成员变量
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d3)+4)+1);
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d3)+4)+2);
      pFun();
    
    cout << "--------------------------------" << endl;
      Dervied4 d4(1,2,3);
      pBase1 = &d4;
      pBase2 = &d4;
      pBase3 = &d4;
      pBase1->foo1();
      pBase2->foo1();
      pBase3->foo1();
    cout << "------------Derived4----------------" << endl;
      pFun = (Fun)*((int*)*(int*)(&d4)+0);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d4)+1);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d4)+2);
      pFun();
      pFun = (Fun)*((int*)*(int*)(&d4)+3);
      pFun();
    
      pFun = (Fun)*((int*)*((int*)(&d4)+2)+0); // Base1 有一个int 类型的成员变量
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d4)+2)+1);
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d4)+2)+2);
      pFun();
    
      pFun = (Fun)*((int*)*((int*)(&d4)+4)+0); // Base1 有一个int 类型的成员变量
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d4)+4)+1);
      pFun();
      pFun = (Fun)*((int*)*((int*)(&d4)+4)+2);
      pFun();
    
      return 0;
    }

    运行结果:

    --------------------------------
    Base1:: foo11
    ------------Derived1----------------
    Base1:: foo110843488
    Base1:: foo210843488
    Base1:: foo310843488
    Dervied1::faa1
    Dervied1::faa2
    --------------------------------
    Dervied2::foo2
    ------------Derived2----------------
    Base1:: foo110843488
    Dervied2::foo2
    Base1:: foo310843488
    Dervied2::fbb2
    Dervied2::fbb3
    --------------------------------
    Base1:: foo11
    Base2:: foo12
    Base3:: foo13
    ------------Derived3----------------
    Base1:: foo110843488
    Base1:: foo210843488
    Base1:: foo310843488
    Dervied3::fcc1
    Dervied3::fcc2
    Base2:: foo110843488
    Base2:: foo210843488
    Base2:: foo310843488
    Base3:: foo110843488
    Base3:: foo210843488
    Base3:: foo310843488
    --------------------------------
    Dervied4::foo1
    Dervied4::foo1
    Dervied4::foo1
    ------------Derived4----------------
    Dervied4::foo1
    Base1:: foo210843488
    Base1:: foo310843488
    Dervied4::fdd
    Dervied4::foo1
    Base2:: foo20
    Base2:: foo30
    Dervied4::foo1
    Base3:: foo20
    Base3:: foo30

  • 相关阅读:
    webuploader之大文件分段上传、断点续传
    人民币数字金额转大写金额
    发现个delphi调用vc写的Dll中包括pchar參数报错奇怪现象
    HTML5 CSS3 专题 : 拖放 (Drag and Drop)
    Cts框架解析(6)-任务的运行
    vector draw 试用期结束的 激活方法
    15_Android中任务栈
    Android之——AIDL深入
    FZU 2155 盟国
    十分简洁的手机浏览器 lydiabox
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332348.html
Copyright © 2020-2023  润新知