最近又重新温习了一下深度探索c++对象模型,中虚拟继承虚表的实现,为了弄清虚表的内存部局情况特写此测试程序。
测试程序分别在windows vs2012下,与linux gcc 4..4.7 20120313 redhat4.4.7-4下
windows vs2012
上图中的偏移为-4表明存在vptr,如果为0说明没有vptr,下面的程序可以说明,而且从图中可以看出虚表中不会有重复的选项
#include <iostream> using namespace std; class X{ public: virtual void funcx(){cout << "X::funcx" << endl;} }; class Y:public virtual X{ public: virtual void funcy(){cout << "Y::funcy" << endl;} virtual void funcx(){cout << "Y::funcx" << endl;} }; class Z:public virtual X{ public: virtual void funcz(){cout << "Z::funcz" << endl;} virtual void funcx(){cout << "Z::funcx" << endl;} }; class D:public Y, public Z{ public: virtual void funcd(){cout << "D::funcd" << endl;} virtual void funcx(){cout << "D::funcx" << endl;} }; typedef void (*func)(); int main(){ func fptr; cout << "sizeof(X) = " << sizeof(X) << endl; cout << "sizeof(Y) = " << sizeof(Y) << endl; cout << "sizeof(Z) = " << sizeof(Z) << endl; cout << "sizeof(D) = " << sizeof(D) << endl; D d; int *vptr = (int*)&d; int *f = (int*)(vptr[0]); cout << "-----------------------" << endl; fptr = (func)(f[0]); fptr(); fptr = (func)(f[1]); fptr(); cout << "-----------------------" << endl; f = (int*)(vptr[1]); cout << *f << endl; cout << "-----------------------" << endl; f = (int*)(vptr[2]); fptr = (func)(f[0]); fptr(); cout << "-----------------------" << endl; f = (int*)(vptr[3]); cout << *f << endl; cout << "-----------------------" << endl; f = (int*)(vptr[4]); fptr = (func)(f[0]); fptr(); return 0; }
#include <iostream> using namespace std; class X{ public: virtual void funcx(){cout << "X::funcx" << endl;} }; class Y:public virtual X{ public: virtual void funcy(){cout << "Y::funcy" << endl;} virtual void funcx(){cout << "Y::funcx" << endl;} }; class Z:public virtual X{ public: //virtual void funcz(){cout << "Z::funcz" << endl;} //对此处进行注释 //virtual void funcx(){cout << "Z::funcx" << endl;} //对此处进行注释 那么就没有了Z 的vptr 但有仍有其指向偏移的指针 }; class D:public Y, public Z{ public: virtual void funcd(){cout << "D::funcd" << endl;} virtual void funcx(){cout << "D::funcx" << endl;} }; typedef void (*func)(); int main(){ func fptr; cout << "sizeof(X) = " << sizeof(X) << endl; cout << "sizeof(Y) = " << sizeof(Y) << endl; cout << "sizeof(Z) = " << sizeof(Z) << endl; cout << "sizeof(D) = " << sizeof(D) << endl; D d; int *vptr = (int*)&d; int *f = (int*)(vptr[0]); cout << "-----------------------" << endl; fptr = (func)(f[0]); fptr(); fptr = (func)(f[1]); fptr(); cout << "-----------------------" << endl; f = (int*)(vptr[1]); cout << *f << endl; cout << "-----------------------" << endl; //f = (int*)(vptr[2]); //fptr = (func)(f[0]); fptr(); cout << "-----------------------" << endl; f = (int*)(vptr[2]); cout << *f << endl; cout << "-----------------------" << endl; f = (int*)(vptr[3]); fptr = (func)(f[0]); fptr(); return 0; }
Linux gcc 4.4.7
此图为linux下的虚继承的内存部局图, 图中可以看出虚表中有重得的选项,但是此图可以看出它相对于win下的部局它没有偏移的指针
#include <iostream> using namespace std; class X{ public: virtual void funcx(){cout << "X::funcx" << endl;} }; class Y:public virtual X{ public: virtual void funcy(){cout << "Y::funcy" << endl;} virtual void funcx(){cout << "Y::funcx" << endl;} }; class Z:public virtual X{ public: virtual void funcz(){cout << "Z::funcz" << endl;} virtual void funcx(){cout << "Z::funcx" << endl;} }; class D:public Y, public Z{ public: virtual void funcd(){cout << "D::funcd" << endl;} virtual void funcx(){cout << "D::funcx" << endl;} }; typedef void (*func)(); int main(){ func fptr; cout << "sizeof(X) = " << sizeof(X) << endl; cout << "sizeof(Y) = " << sizeof(Y) << endl; cout << "sizeof(Z) = " << sizeof(Z) << endl; cout << "sizeof(D) = " << sizeof(D) << endl; D d; int *vptr = (int*)&d; int *f = (int*)(vptr[0]); cout << "-----------------------" << endl; fptr = (func)(f[0]); fptr(); fptr = (func)(f[1]); fptr(); cout << "-----------------------" << endl; f = (int*)(vptr[1]); cout << *f << endl; cout << "-----------------------" << endl; f = (int*)(vptr[2]); fptr = (func)(f[0]); fptr(); cout << "-----------------------" << endl; f = (int*)(vptr[3]); cout << *f << endl; cout << "-----------------------" << endl; f = (int*)(vptr[4]); fptr = (func)(f[0]); fptr(); return 0; }
从图中能够反应出,类的大小与win的差距还是很大的