類對象大小測試2

#include <iostream>

using namespace std;


/*
創建對象A
創建對象BA
創建對象A
創建對象BA
銷燬對象BA
銷燬對象A
銷燬對象BA
銷燬對象A
創建對象C
創建對象BC
創建對象C
創建對象BC
line=173  fun_bc1
line=178  fun_bc2
銷燬對象BC
銷燬對象C
line=173  fun_bc1
line=178  fun_bc2
銷燬對象C
---------------------------------------------
size0f(A)=4
size0f(B)=4
size0f(C)=12
size0f(BA)=8
size0f(BC)=16
size0f(D)=8
size0f(BD)=12
創建對象D
line=123
創建對象D
line=198
line=198
size0f(Edata)=4

測試結論:
1.子類對象大小=當前子類成員函數大小+父類對象大小+有虛函數的話還要加4(這個是實現動態虛表的指針)
2.成員函數不佔用對象空間大小,成員函數是在代碼段
3.若設置的類可以被其他類可繼承,在析構函數前應該加virtual

基類的析構函數加了virtual就可以動態綁定派生類的析構函數,這樣的話,在執行多態後刪除其對象,就可以在刪除對象的時候執行派生類的析構函數了(當然執行基類的析構函數是一定會的)。否則不會執行派生類的析構函數。
*/
class A //1字節   2個成員函數不佔空間,本應該是0字節,但創建對象要用空間,所以編譯器爲其分配1個字節大小 
{
public:
	A()
	{
		cout<<"創建對象A"<<endl;
	};

	virtual  ~A()
	{
		cout<<"銷燬對象A"<<endl;
	};

	//void fun_a1();
	//void fun_a2();
};
/*
void A::fun_a1()
{
	cout<<"fun_a1"<<endl;
}

void A::fun_a2()
{
	cout<<"fun_a2"<<endl;
}
*/

class B //4字節   有一個int成員變量,所以佔用4字節  
{
public:
	B()
	{
		cout<<"創建對象B"<<endl;
	};
	~B()
	{
		cout<<"銷燬對象B"<<endl;
	};

	int idata;

	void fun_b1();
	void fun_b2();
};


void B::fun_b1()
{
	cout<<"fun_b1"<<endl;
}

void B::fun_b2()
{
	cout<<"fun_b2"<<endl;
}

class C //12字節   有2個int成員變量+1個虛表,所以佔用12字節  
{
public:
	C()
	{
		cout<<"創建對象C"<<endl;
	};
	~C()
	{
		cout<<"銷燬對象C"<<endl;
	};

	int idataC;
	int idataD;

    virtual void fun_c1();//虛表4字節  這個不加virtual,程序會在delete base_c;崩潰,因爲BC類的fun_c1加virtual
	void fun_c2();//0-字節
};


void C::fun_c1()
{
	cout<<"line="<<__LINE__<<"   fun_c1"<<endl;
}

void C::fun_c2()
{
	cout<<"line="<<__LINE__<<"   fun_c2"<<endl;
}

class D //8字節   有1個int成員變量,佔用4字節  還有虛函數佔用4字節(一個或多個都只佔用一個指針)
{
public:
	D()
	{
		cout<<"創建對象D"<<endl;
	};
	~D()
	{
		cout<<"銷燬對象D"<<endl;
	};

	int idataD;

	virtual void v_fun1();
	virtual void v_fun2();
	virtual void v_fun3();
};


void D::v_fun1()
{
    cout<<"line="<<__LINE__<<endl;
}

void D::v_fun2()
{
	cout<<"line="<<__LINE__<<endl;
}
void D::v_fun3()
{
	cout<<"line="<<__LINE__<<endl;
}

class BA:public A //4+1(0)-->4  BA成員變量佔用4字節,A佔用1字節,但因爲A沒有成員變量,編譯器會進行優化成0字節,所以這個也只佔用4字節.但VC測試可能沒有優化還是8個字節
{
public:
	BA()
	{
		cout<<"創建對象BA"<<endl;
	};

	~BA()
	{
		cout<<"銷燬對象BA"<<endl;
	};

	int idata;
};


class BC:public C //4+8-->12   成員變量4字節+C類12字節共16字節
{
public:
	BC()
	{
		cout<<"創建對象BC"<<endl;
	};
	 ~BC()
	{
		cout<<"銷燬對象BC"<<endl;
	};

	int idata;

	virtual void fun_c1();//0-字節 因爲C類中已有virtual表,所以這裏虛表不佔空間了
	void fun_c2();//0-字節
};


void BC::fun_c1()
{
	cout<<"line="<<__LINE__<<"  fun_bc1"<<endl;
}

void BC::fun_c2()
{
	cout<<"line="<<__LINE__<<"  fun_bc2"<<endl;
}


class BD:public D //8+8(4)-->12   內部成員變量4字節+虛函數4字節+D類成員變量4字節=12字節
{
public:
	BD(){};
	~BD(){};
	
	virtual void v_fun1();//4
	virtual void v_fun2();
	virtual void v_fun3();

	int idata;//4
};


void BD::v_fun1()
{
	cout<<"line="<<__LINE__<<endl;
}

void BD::v_fun2()
{
	cout<<"line="<<__LINE__<<endl;
}
void BD::v_fun3()
{
	cout<<"line="<<__LINE__<<endl;
}


typedef enum Edata
{
	KIDEL=1,
    KRUN=2,
};

int main()
{
	A  *base_a;
	BA *ba = new BA;
	BA *ba2 = new BA;
	
	if (ba)
    {
		delete ba;
	}

	base_a = ba2;
	if (base_a)
    {
		delete base_a;
	}

	C  *base_c;
	BC *bc = new BC;
	BC *bc2 = new BC;

	bc->fun_c1();
	bc->fun_c2();
	if (bc)
    {
		delete bc;
	}

	base_c = bc2;//因爲 C類的構造函數不是virtual 虛函數,在基類指向子類對象進行刪除時,就不會調用子類的析構,從而會造成派生類中申請的空間就得不到釋放從而產生內存泄漏
	bc2->fun_c1();
	bc2->fun_c2();
	if (base_c)
    {
		delete base_c;
	}


	cout<<"---------------------------------------------"<<endl;
	D *d;
	BD *bd;
	cout<<"size0f(A)="<<sizeof(A)<<endl;
	cout<<"size0f(B)="<<sizeof(B)<<endl;
	cout<<"size0f(C)="<<sizeof(C)<<endl;
	cout<<"size0f(BA)="<<sizeof(BA)<<endl;
	cout<<"size0f(BC)="<<sizeof(BC)<<endl;

	cout<<"size0f(D)="<<sizeof(D)<<endl;
	cout<<"size0f(BD)="<<sizeof(BD)<<endl;

	d = new (D);
	d->v_fun1();

	bd = new (BD);
	bd->v_fun1();

	d = bd;
	d->v_fun1();


	cout<<"size0f(Edata)="<<sizeof(Edata)<<endl;

	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章