类的大小计算

/********************************************
	*@author: weedge 
	*@date: 19/07/2011
	*@coment: 
			c++对象模型,类在内存中的分配情况,主要是对类中引入虚函数以及虚继承的情况的了解
	    _vptr:指向存放虚函数地址数组_vtable的指针。
	   _vtable:存放类中虚函数地址的数组。
	   
	   typedef void (__cdecl *PVFN)(void);//通用虚函数指针PVFN
	   
	   typedef struct{
	   		//为了支持RTTI(Run-Time Type Identification)机制:运行时检查对象类型信息。
	   		//为每个多态类创建一个type_info对象,并保存在vtable中的固定位置(一般为第一个位置,取决于编译器)
	   		type_info *_pTypeInfo;
	   		PVFN _arrayOfPvfn[];//虚函数个数由初始语句确定
	   }VTABLE;
	   
	   基类A 和 C;   
	   B继承A;   
	   AC多继承A 和 C;
	   AA和BB虚继承A, AABB多继承AA和BB; 
************************************************/

#include<iostream>
using namespace std;

class A
{
	/*
	在类中有虚函数的情况下:
	类中隐藏了指向装有指向虚函数指针的数组的指针 _vptr;
	而该虚函数的地址存放在_vtable中;
	_vtable分配在静态数据区域,_vptr是类隐藏的数据成员。
	*/	
public:
	A():a(0){printf("this is A CLASS\n");}
		
	virtual ~A(){}
	int get_a()const{return a;}
	void set_a(int a){this->a = a;}
private:
	int a;
	static int count;//静态数据区域,不计入类的分配空间中。
};

class C
{
public:
	C():c(0){printf("this is C CLASS\n");}	
	virtual ~C(){}
	int get_c()const{return c;}
	void set_c(int c){this->c = c;}
private:
	int c;
};


class B : public A
{
	/*
	公有继承:A的成员属性权限不变。
	其B中虚函数的地址放入B中的_vtable中,B中隐藏的数据成员_vptr指向该虚表_vtable。
	由于是单继承,如果基类A中有_vptr数据成员,则子类B中的也是同一个_vptr成员(继承)。
	*/
public:
	B():b(0){printf("this is B CLASS\n");}
	virtual ~B(){}
	int get_b()const{return b;}
	void set_b(){this->b = b;}
private:
	int b;
};

class BB : virtual public A
{
	/*
	虚继承:基类A中的成员函数变为虚函数,作为子类BB中的成员函数,
	与不使用虚继承不同的是BB中会重新分配一个隐藏数据成员_vptr,
	其指向存有A类中所有函数地址数组_vtable的指针。
	而BB中虚函数的地址放入BB中的_vtable中,BB中隐藏的数据成员_vptr指向该虚表_vtable。
	这样存在两个指向不同虚表地址的_vptr数据成员。
	虚继承主要是用于“菱形继承”的情况,虚继承抽象基类,这样子类中有2个不同虚表,
	防止下个子类中的实例对象中调用抽象基类的函数成员时,出现“二义性”。
	*/
public:
	BB():bb(0){printf("this is BB CLASS\n");}
	virtual ~BB(){}
	int get_bb()const{return bb;}
	void set_bb(){this->bb = bb;}
private:
	int bb;
};

class AA : virtual public A
{
public:
	AA():aa(0){printf("this is AA CLASS\n");}
	virtual ~AA(){}
	int get_aa()const{return aa;}
	void set_aa(){this->aa = aa;}
private:
	int aa;
};


class AC : public A, public C
{
	/*
	多继承:派生类从多个基类继承。
		派生类从每个分支中继承一个vptr,编译器生成多个vtable,一一对应。
		至于派生类AC中的虚函数地址应该是放入其中一个vtable中,具体情况待进一步了解。
	*/
public:
	AC():ac(0){printf("this is AC CLASS\n");}
	virtual ~AC(){}
	int get_ac()const{return ac;}
	void set_ac(){this->ac = ac;}
private:
	int ac;
	};

class AABB : public AA, public BB
{
	/*
	多继承:派生类从多个基类继承。
		派生类从每个分支中继承一个vptr,编译器生成多个vtable,一一对应。
		至于派生类AC中的虚函数地址应该是放入其中一个vtable中,具体情况待进一步了解。
		但是这里的继承属于“菱形继承”的情况,即为了防止AABB中对基类A中的成员函数访问出现“二义性”,
		将A的派生类AA和BB采用虚继承。所以派生类AA和派生类BB中有指向同一个基类A中vtable的vptr,
		即AA和BB的子类AABB也同时拥有一个隐藏的数据成员vptr.
	*/
public:
	AABB():aabb(0){printf("this is AABB CLASS\n");}
	virtual ~AABB(){}
	int get_aabb()const{return aabb;}
	void set_aabb(){this->aabb = aabb;}
private:
	int aabb;
	};

int main()
{
	cout<<sizeof(A)<<endl;//所以A的分配空间大小为sizof(int)+ sizeof(PVFN*) = 8
	cout<<sizeof(B)<<endl;//所以B的分配空间大小为2*sizof(int)+ sizeof(PVFN*) = 12
	cout<<sizeof(BB)<<endl;//所以BB的分配空间大小为2*sizof(int)+ 2*sizeof(PVFN*) = 16
	cout<<sizeof(AC)<<endl;//所以AC的分配空间大小为3*sizof(int)+ 2*sizeof(PVFN*) = 20
	cout<<sizeof(AABB)<<endl;//所以AABB的分配空间大小为4*sizof(int)+ 3*sizeof(PVFN*) = 28		
	return 0;
	
}


你可能感兴趣的:(类的大小计算)