转载:
[C++对象模型][8]多重继承与虚函数表
一 多重继承
1) 代码:
Code #include <iostream> using namespace std; class B1 { public: int x; virtual void v1(){ cout << "B1::v1" << endl; } void f1(){cout << "B1::f1" << endl; } }; class B2 { public: int y; virtual void v2(){ cout << "B2::v2" << endl; } void f2(){ cout << "B2::f2" << endl; } }; class B3 { public: int z; virtual void v3(){ cout << "B3::v3" << endl; } void f3(){ cout << "B3::f3" << endl; } }; class D : public B1, public B2, public B3 { public: int a; void v3(){ cout << "D::v3" << endl; } virtual void vD(){ cout << "D::vD" << endl; } };
2)类图:
3)VS2008的编译选项查看布局:
4)可视化表示:
5)代码验证:
Code typedef void (*Fun)(); void PrintMember(int *pI) { cout << *pI << endl; } void PrintVT(int *pVT) { while(*pVT != NULL) { (*(Fun*)(pVT))(); pVT++; } } void PrintVTAndMember(B1 *pD) { int *pRoot = (int*)pD; int *pVTB1 = (int*)*(pRoot + 0);PrintVT(pVTB1); int *pMB1 = pRoot +1; PrintMember(pMB1); int *pVTB2 = (int*)*(pRoot + 2);PrintVT(pVTB2); int *pMB2 = pRoot +3; PrintMember(pMB2); int *pVTB3 = (int*)*(pRoot + 4);PrintVT(pVTB3); int *pMB3 = pRoot +5; PrintMember(pMB3); } void TestVT() { B1 *pB1 = new D(); D *pD = dynamic_cast<D*>(pB1); pD->x = 10; pD->y = 20; pD->z = 30; pD->a = 40; PrintVTAndMember(pD); delete pD; }
6) 验证代码运行结果:
7)总结:
与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表,当子类对父类的虚函数有重写时,子类的函数覆盖父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面。
二 多重继承运行时类型转化
1)代码验证:
Code void TestDynamicCast() { B1 *pB1 = new D(); cout << "B1:" << pB1 << endl; D *pD = dynamic_cast<D*>(pB1); cout << "D:"<< pD << endl; B2 *pB2 = dynamic_cast<B2*>(pB1); cout << "B2:" << pB2 << endl; B3 *pB3 = dynamic_cast<B3*>(pB1); cout << "B3:" << pB3 << endl; delete pD; }
2)验证代码的运行结果:
3)总结:
从多重继承的内存布局,我们可以看到子类新加入的虚函数被加到了第一个基类的虚函数表,所以当dynamic_cast的时候,子类和第一个基类的地址相同,不需要移动指针,但是当dynamic_cast到其他的父类的时候,需要做相应的指针的移动。
三 完!