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

posted on 2014-04-23 00:09  胡永光  阅读(437)  评论(0编辑  收藏  举报

导航