預設建構函式

預設建構函式是 C++ 及其他一些面向物件程式設計語言中，物件的不需要引數即可呼叫的建構函式。

概述

物件生成時如果沒有顯式地呼叫建構函式，則預設建構函式會被自動呼叫。C++ 標準規定，如果建構函式沒有引數（nullary），或者建構函式的所有引數都有預設值（default value），都算作預設建構函式。一個類只能有一個預設建構函式。

例如，顯式定義、使用 “預設建構函式”：

class MyClass

{

public:

MyClass ; //constructor declared

private:

int x;

};

MyClass :: MyClass //constructor defined

{x = 100;}

int main

{MyClass object; //object created} // => default constructor called automatically

下述例子是動態生成物件時，顯示呼叫了預設建構函式：

int main

{MyClass * pointer = new MyClass ; //object created

} // => default constructor called automatically

MyClass (int i = 0)

C++ 中，預設建構函式會在下列情形被自動呼叫：

物件被定義時無引數，例如：MyClass x;; 或動態分配物件時無引數列表，例如：new MyClass 或 new MyClass ; 預設建構函式用於初始化物件。
物件陣列被定義時，例如：MyClass x10;; 或被動態分配時，例如：new MyClass 10; 預設建構函式初始化陣列的每個物件。
當派生類在其初始化列表（initializer list）中沒有顯式呼叫其基類物件的建構函式時，基類的預設建構函式被自動呼叫。
當一個類的建構函式的初始化列表中沒有顯式呼叫其物件成員（object component 或 object-valued field）的建構函式時，物件成員的預設建構函式被自動呼叫。
C++ 標準程式庫中，一些容器的填充值使用了值物件的預設建構函式，如果這些值沒有顯式地給出。例如：vector (10); 用 10 個元素初始化 vector，這些元素用其預設建構函式來初始化。

在上述這些情形中，如果被初始化地物件沒有預設建構函式，則編譯時報錯。

如果一個類沒有顯式定義建構函式，編譯器將為其隱式地定義預設建構函式（下文給出了例外情形）。隱式定義的預設建構函式的函式體為空。例如：

class MyClass

{int x; //no constructor}; // => the compiler produces an (implicit) default constructor

int main

{MyClass object; //no error: the (implicit) default constructor is called

}

如果類顯式地定義了一些建構函式，但不是預設建構函式，編譯器則不會為該類隱式定義預設建構函式。該類就沒有預設構造函數了。也就是說，並不是所有類都有預設建構函式。這是很多常見錯誤的原因。例如：

class MyClass

{

public:

MyClass (int y); //a constructor

private:

int x;

};

MyClass :: MyClass (int y)

{x = y;}

int main

{MyClass object (100); //constructor called

MyClass *pointer; //for declaration do not need to know about existing constructors

pointer = new MyClass ; //error: no default constructor

return 0;

}

如果類的基類沒有預設建構函式，那麼編譯器也不會為該類隱式地定義預設建構函式。因為該類即使隱式地定義預設建構函式，也無法初始化其基類。例如：

class A

{

public:

	explicit A (int)};

class B: public A

{

};

int main

{B b1; // 編譯報錯}

如果類的基類的預設建構函式為私有，那麼編譯器會為該類隱式地定義預設建構函式，但編譯報錯 “cannot access private member declared in class 基類名字”。例如：

class A

{A ;

public:

};

class B: public A

{

};

int main

{B b1; // 編譯報錯}

對於 union 資料型別，如果它包含了一個成員有非預設的建構函式，那麼這個 union 型別的建構函式必須顯式呼叫這個成員型別的建構函式。例如：

struct bar {bar ;

	bar (int) ;};

union foo {

	int i;

	float j;

	bar b;

//foo : b ; // 只有增加這行，才能成功地構造一個 foo 型別的物件};

foo vvv; //syntax error: attempting to reference a deleted function

進階概念

class-name ﻿ = default; 稱作 “顯式地被預設”（explicitly-defaulted）。

class-name ﻿ = delete; 稱作 “預設建構函式被刪除”（The default constructor is deleted.）。

平凡的預設建構函式（Trivial default constructor）是不執行任何操作的建構函式。 所有與 C 語言相容的資料型別（POD 型別）都是平凡的預設可構造。如果滿足以下所有條件，則類 T 的預設建構函式是平凡的（即不執行任何操作）：

建構函式不是使用者提供的（即，在其第一個宣告中隱式定義或預設）。
T 沒有虛成員函式。
T 沒有虛基類。
T 沒有帶有預設的初始值設定項的非靜態成員（自 C++11 起）
T 的每個直接基類都有一個平凡的預設建構函式。
類型別（或其陣列）的每個非靜態成員都有一個平凡的預設建構函式。

隱式宣告的預設建構函式：如果沒有為類型別提供任何型別的使用者宣告的建構函式，則編譯器總是將預設建構函式宣告為其類的內聯公共成員。如果存在一些使用者宣告的建構函式，使用者仍然可以強制編譯器使用關鍵字 default 自動生成預設建構函式。（自 C++11 起）

隱式定義的預設建構函式：如果隱式宣告或 “顯式地被預設” 的預設建構函式未被刪除，則由編譯器定義（即生成函式體並編譯），與具有空主體和空初始值列表的使用者定義建構函式具有相同的效果。也就是說，它呼叫該類的基類和非靜態成員的預設建構函式。 如果存在一些使用者定義的建構函式，使用者仍然可以強制編譯器自動生成預設建構函式，否則將使用關鍵字 default 隱式宣告該預設建構函式。

被刪除的預設建構函式（Deleted default constructor），如果滿足以下任一條件，則類 T 的隱式宣告或顯式預設的預設建構函式為已刪除 (C++11 起)：

T 是一個 union，其所有變體成員都是 const 限定型別（或是其多維陣列）。
T 是一個非 union 的類，且所有匿名聯合成員都是 const 限定型別（或其多維陣列）。
T 有一個引用型別的非靜態資料成員，沒有預設初始化值 (C++11 起)。
T 具有 const 限定型別的非變體、非靜態、非 const 預設可構造的資料成員（或其多維陣列），沒有預設初始化值 (C++11 起)。
T 具有類型別為 M（或其多維陣列）的潛在可構造子物件，使得 M 有一個解構函式，該解構函式已被刪除或無法訪問預設建構函式

如果不存在使用者定義的建構函式並且隱式宣告的預設建構函式並不平凡，則使用者仍然可以使用關鍵字 delete 禁止編譯器自動生成隱式定義的預設建構函式。

struct F

{

int& ref; //reference member

const int c; //const member

// F::F is implicitly defined as deleted};