1. 程式人生 > >C++編譯器生成預設的建構函式的幾種情況

C++編譯器生成預設的建構函式的幾種情況

問題:對c++初學者來說存在一個誤區,如果類沒有定義任何建構函式,編譯器會自動生成預設的建構函式。  

注意:這種說法是錯誤的。

正確的說法:惟有預設建構函式”被需要“的時候編譯器才會合成預設建構函式。

那什麼情況下是“被需要”的時候?

以下有四種情況編譯器會自動合成預設建構函式

情況1 含有類物件資料成員,該類物件型別有預設建構函式

即:一個class含有類物件資料成員,該類物件型別有預設建構函式sA包含了一個物件成員objectB,而這個物件成員定義了(classB的)預設建構函式,那麼編譯器會為classA合成一個預設建構函式

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
};
class B
{
public:
	A a;
	int num;
};
void Test()
{
	B b;
	cout << b.num << endl;
}

int main()
{
Test();
return 0;
}


 原因: 因為類成員物件有預設建構函式,那麼編譯器就需要 顯式的來呼叫這個類成員物件的 建構函式。而編譯器想顯式的呼叫類成員物件的預設建構函式,就需要自己來合成一些程式碼來呼叫。但是記住,編譯器合成的預設建構函式
僅僅呼叫類成員物件的預設建構函式,而不對我們類裡面的其它變數做任何初始化操作

情形2 基類帶有預設建構函式的派生類

  當一個類派生自一個含有預設建構函式的基類時,該類也符合編譯器需要合成預設建構函式的條件。編譯器合成的預設建構函式將根據基類宣告順序呼叫上層的基類預設建構函式。

 原因:因為派生類被合成時需要顯式呼叫基類的預設建構函式。

class Base
{
public:
	Base()
	{
		cout << "Base()" << endl
; } };

class Derived :public Base
{
public:
int d;
};

void Test()
{
Derived d;
}

int main()
{
Test();
return 0;
}


情形3 帶有虛擬函式的類

         類帶有虛擬函式可以分為兩種情況:

  1. (1)類本身定義了自己的虛擬函式
            (2) 類從繼承體系中繼承了虛擬函式(成員函式一旦被宣告為虛擬函式,繼承不會改變虛擬函式的”虛性質“)。
       這兩種情況都使一個類成為帶有虛擬函式的類。這樣的類也滿足編譯器需要合成預設建構函式的類,原因是含有虛擬函式的類物件都含有一個虛表指標vptr,編譯器需要對vptr設定初值以滿足虛擬函式機制的正確執行,編譯器會把這個設定初值的操作放在預設建構函式中。如果設計者沒有定義任何一個預設建構函式,則編譯器會合成一個預設建構函式完成上述操作,否則,編譯器將在每一個建構函式中插入程式碼來完成相同的事情。
情形4 帶有虛基類的類      虛繼承也會在子類物件中被合成一個指向虛基類的指標,因此也要被初始化,所以必須要建構函式,虛基類或者虛繼承保證子類物件中只有一份虛基類的物件。     總結一下: 不符合以上4種情形的而且沒有宣告任何建構函式的,編譯器並不會合成預設的建構函式;                    並且合成的預設建構函式並不會初始化類的內建型別複合型別的資料成員。