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的差距还是很大的

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

时间: 2024-11-01 12:10:36

c++内存部局(虚继承)的相关文章

C++ 多继承和虚继承的内存布局(Memory Layout for Multiple and Virtual Inheritance)

警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中,我们解释由gcc编译器实现多继承和虚继承的对象的布局.虽然在理想的C++程序中不需要知道这些编译器内部细节,但不幸的是多重继承(特别是虚拟继承)的实现方式有各种各样的不太明确的结论(尤其是,关于向下转型指针,使用指向指针的指针,还有虚拟基类的构造方法的调用命令). 如果你了解多重继承是如何实现的,你就能预见到这些结论并运用到你的代码中.而且,如果你关心性能,理解虚拟继承的开销也是非常有用的.最后,这很有趣. :-) 多重

转载:C++ 多继承和虚继承的内存布局

C++ 多继承和虚继承的内存布局[已翻译100%] 英文原文:Memory Layout for Multiple and Virtual Inheritance 标签: <无> run_mei 推荐于 4年前 (共 14 段, 翻译完成于 10-17) 评论 46 分享 收藏 198 参与翻译 (5人) : super0555, polarisxxm, Ley, zaobao, 开源中国吹牛第一仅中文 | 中英文对照 | 仅英文 | 打印此文章 警告. 本文有点技术难度,需要读者了解C++和

C++ 多继承和虚继承的内存布局(转)

转自:http://www.oschina.net/translate/cpp-virtual-inheritance 警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中,我们解释由gcc编译器实现多继承和虚继承的对象的布局.虽然在理想的C++程序中不需要知道这些编译器内部细节,但不幸的是多重继承(特别是虚拟继承)的实现方式有各种各样的不太明确的结论(尤其是,关于向下转型指针,使用指向指针的指针,还有虚拟基类的构造方法的调用命令). 如果你了解多重继承是如何实现的,你就能

解析虚函数表和虚继承

之前大二在学C++的时候一直对虚函数和虚继承有些晕(其实好像就是对virtual这个关键字不太熟悉)现在又学习到了一些,对虚函数表和虚继承的机制有了一点更深入的了解. 关于虚函数以及虚继承的基础知识,我自己也总结了一下,点击浅谈C++多态和C++继承可查看,在继承的总结的时候,我没有总结关于虚继承的知识,而且在多态总结也没有设计到太多的虚函数的知识,我是想把这两块集中在一起讲下,也算是自己对virtual关键字有个比较深入的了解吧.(本文所有代码均在VS2013编译器win32下测试) 另外对于

继承,虚继承机制

继承体系中的作用域: 1.在继承体系中基类和派生类都有独立的作用域. 2.子类和父类中有同名成员.子类成员将屏蔽父类对成员的直接访问.(在子类成员函数中,可以使用基类:基类成员访问)-隐藏-重定义 3.注意在实际中在继承体系里面最好不要定义同名的成员. 注意事项: (1)当基类构造函数不带参数时, 派生类不一定需要定义构造面数, 系统会自动的调用基类的无参构造函数; 然而当基类的构造函数那怕只带有一个参数, 它所有的派生类都必须定义构造函数, 甚至所定义的派生类构造函数的函数体可能为空, 它仅仅

多继承(虚继承)派生类对象内存结构

在这里谈一下虚继承.前面写过派生类对象的内存结构,都是基于VS2010编译器的,不同的编译器对于继承的处理不同,但本质都是一样的. 虚继承是解决共享基类问题的.例如在菱形继承中 如果不使用虚继承,基类A在D中会有两个,这不仅浪费内存,还会造成歧义.使用虚继承就可以解决基类共享的问题. 要想在派生类中共享基类(例如在D对象中只有一个A对象,这时候D对象中的B对象和C对象都可以查找到A,而不是在B对象和C对象中各含有一个A对象). 先看下面一个例子: #include<iostream> usin

虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte

#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout << "A:A" <<endl; } virtual void getb(){ cout << "A:B" <<endl; } }; class B :public A{ public: B(){} virtual void g

c/c++: c++继承 内存分布 虚表 虚指针 (转)

http://www.cnblogs.com/DylanWind/archive/2009/01/12/1373919.html 前部分原创,转载请注明出处,谢谢! class Base { public:  int m_base; }; class DerivedA: public Base { public:  int m_derivedA; }; class DerivedB: public Base { public:  int m_derivedB; }; class DerivedC

多重继承及虚继承中对象内存的分布

http://www.uml.org.cn/c++/201305163.asp 个人总结:多重继承时,对象中保存多个虚函数表指针, 虚拟继承时,对象中保存多个虚函数表指针,但被虚拟继承的基类对象在被继承的对象中只有一份,这个是靠共享其内容实现的.且共享的内容在子类对象的最后. 虚拟继承 为了避免上述Top类的多次继承,我们必须虚拟继承类Top. 1 class Top2 {3 public:4 int a;5 };67 class Left : virtual public Top8 {9 pu