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