首页 > 代码库 > c++内存部局(虚继承)

c++内存部局(虚继承)

最近又重新温习了一下深度探索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的差距还是很大的