C++的建構函式
1. 類沒實現,編譯器提供預設建構函式
2. 類自己實現,編譯器不再提供任何建構函式
3. 類實現帶參數建構函式,編譯器也不會提供預設建構函式
4. 在賦值重載和帶參數建構函式之間,編譯器優先選擇建構函式。
5. 先調用基類的建構函式,再調用衍生類別的建構函式,解構函式是先析構衍生類別,再析構基類。
C++的記憶體布局
1. 空類大小為1個位元組
class Base
{};
2. 帶virtual方法的類大小必須多加上4個位元組,由於virtual是需要一個vptr來指向vtable。
class Base
{
virtual void foo() {}
};
3. 所有static的欄位大小不應該算到對象當中,如
class Base
{
public:
static int maxValue;
};
sizeof對象出來的結果還是1個位元組。
4. 所有的方法都不佔有直接,如:
class Base
{
void foo(){}
};
sizeof對象出來的結果還是1個位元組。
5. 基類的布局在衍生類別之上
C++純抽象類別
C++中沒有interface和abstract關鍵字(C#/Java中有),但是我們可以通過純抽象類別來實現。
class IBase
{
virtual public void foo() = 0;
static const int count = 0;
};
6. 解構函式為什麼要用virtual聲明
class Base
{
public:
Base() {cout << "Base constructor" << endl; }
~Base() { cout << "Base destructor" << endl; } // 這裡有沒有virtual 有著明顯的區別
};
class Extand : public Base
{
public:
Extand() { cout << "Extand constrcutor" << endl; }
~Extand() { cout << "Extand destructor" << endl;}
};
下面是兩種調用方式:
(1)
Base *p = new Extand();
delete p;
輸出:
Base constructor
Extand constrcutor
Base destructor
這裡少了Extand destructor,這說明virtual在解構函式中扮演了一個傳遞資訊的角色。其實我們的本意是想得到2的結果,但是已經沒有資訊告訴編譯器,去哪裡調用衍生類別的解構函式了。
------------------------------------------
(2)
Extand *p = new Extand();
delete p;
輸出:
Base constructor
Extand constrcutor
Extand destructor
Base destructor
------------------------------------------
那麼c++是如何去實現virtual的呢?由於virtual是運行時才確定的,因此c++對包含有virtual聲明的類產生一個vptr指標,指向一個vtable。當基類的某個virtual方法被衍生類別重寫後,衍生類別的方法自動變為virtual, 方法地址會自動加到基類的vtable中。這樣就產生了傳遞的效果,我們也可以有效明確的調用到衍生類別的方法,在經過類型向上傳遞後。