C++中的多重继承有两种:一种是多层次的继承,另外就是多基类单层次的继承。这里介绍下多基类继承中基类和派生类在内存布局上的关系。先看下面的一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <iostream> #include <iomanip> //~ #include <sqlite.h> //~ #include <mysql/mysql.h> using namespace std; class B1 { public: void f1(){cout<<"B1::f1()"<<endl;} virtual void v1(){cout<<"B1::v1()"<<endl;} int x; }; class B2 { public: void f2(){cout<<"B2::f2()"<<endl;} virtual void v2(){cout<<"B2::v2()"<<endl;} int y; }; class B3 { public: void f3(){cout<<"B3::f3()"<<endl;} virtual void v3(){cout<<"B3::v3()"<<endl;} int z; }; class D:public B1, public B2, public B3 { public: void f1(){cout<<"D::f1()"<<endl;} virtual void v1(){cout<<"D::v1()"<<endl;} virtual void d(){cout<<"D::d()"<<endl;} int n; }; int main () { D d; D* pd = &d; B1 * pb1 = &d; B2 * pb2 = &d; B3 * pb3 = &d; cout<<pd<<endl; cout<<pb1<<endl; cout<<pb2<<endl; cout<<pb3<<endl; return 0; } |
程序中输出了派生类对象d的地址,以及将其赋给相应基类指针后的地址,输出结果:
0xbfbe40e8 0xbfbe40e8 0xbfbe40f0 0xbfbe40f8
可见,将d转换成第一个基类B1时,地址是不变的,而转化到其他基类时,地址会发生变化。对象的d的内存布局可以用下图来表示:

class D
这里面有三张函数表,分别对应d的三个基类。事实上,d的虚函数d()的地址保存在了基类B1对应的虚函数表内。从多重继承的内存布局,我们可以看到子类新加入的虚函数被加到了第一个基类的虚函数表,所以当dynamic_cast的时候,子类和第一个基类的地址相同,不需要移动指针,但是当dynamic_cast到其他的父类的时候,需要做相应的指针的移动。
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
Be the first to comment on this entry.