#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;
}