您的位置:首页 > 编程语言 > C语言/C++

c++对象模型探讨

2012-10-08 11:39 141 查看
有一句经典的话,程序是写给人看的,顺便给机器执行。那么对于c++对象在内存中是怎么表示的。下面用win xp(32位) + vc++ 6.0对c++内存对象模型进行简明的探讨。





上面的类很简明,分别有两个虚函数一个int变量以及一个公有函数。那么请问一个A类的对象在内存的大小为多少即sizeof(A)?答案为8字节。因为一个int型变量为4字节,32位机加一个虚函数列表。那么继续看下面的单继承关系。





这里的sizeof(C)为多少?答案为12字节。在内存中即将两个结构叠合一起即m_ia+m_ic+vftables(虚函数列表),同时虚函数列表只有一张。




这里多继承的情况下sizeof(c)为多少?答案为20字节。可能为有疑问,因为m_ia+m_ib+m_ic+vftable_c(c的虚函数列表)应该为16字节,查看内存得知其实这里有两张虚函数列表,一个为B的,一个为A的。这里的答案可以自己上机得到,然后再思考为什么是这样。我们知道c++有几种类型的转换,static_cast,dynamic_cast,reinterpret_cast等。一般我们可以简单认为对于高精度向低精度转换时,只要将多余的截掉就ok啦。这种转换即保证指针的值不变,只改变所指向内存的大小,例如double
a ; int *p = &a 。但是对于这里的多继承关系,如上例c继承b和a。那么将c类对象指针转换为b类指针其值不变,那么转换为a呢?答案请自己上机验证。附上程序,调试过程以及图则略:

#include<stdio.h>
#include<iostream>
using namespace std;
class A {
 public:
	 A():m_ia(0)
	 {}
	 virtual void  vfun0() ;
	 virtual void  vfunA1();
	 int m_ia  ;
	 void   funA() ;
} ;

void  A::vfun0()
{
		 cout<<" vfunA0 called "<<endl ;
}
void  A::vfunA1()
{
		 cout<<" vfunA1 called "<<endl ;
}
void A::funA()
 {
		 cout<<"funA  called "<<endl ;
}

class B {
 public:
	 B():m_ib(0)
	 {}
	 virtual  void vfun0() ;
	 virtual  void vfunB1() ;
	 int m_ib  ;
	 void   funB() ;
} ;

void B::vfun0()
{
		 cout<<" vfunB0 called "<<endl ;
}
void B::vfunB1()
{
		 cout<<" vfunB1 called "<<endl ;
}
void B::funB()
{
  cout<<"funB  called "<<endl ;
}

class C : public B , public A{
public:
	C():m_ic(0)
	{}
	virtual  void  vfun0();
	virtual  void  vfun1();
	 int  m_ic ;
}; 

void C::vfun0()
{
  cout<<" vfunC0 called "<<endl ;
}

void  C::vfun1()
{
  cout<<" vfunC1 called "<<endl ;
}
int main ()
{
	A    *pa , a ;
         B   *pb ,b   ;
	C c ;
	pa  = reinterpret_cast<A*>(&c) ;
	printf("the pa :0x%p\n",pa);
	pa->vfun0();
	pa->vfunA1();
	printf("pa->vfunA1:%p\n",pa->vfunA1);
	printf("c.vfun1:%p\n",c.vfun1);
	pb  = &c ;
	printf("the pb :0x%p\n",pb);
	pb->vfun0();
	pb->vfunB1();
	printf("c size:%d\n",sizeof(c));
	c.vfun1();
	printf("%d\n",sizeof(c));
	return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: