當基類**僅有帶參數建構函數** (無預設建構函數) 時,衍生類**必須**在成員初始化清單中顯式呼叫基類建構函數,否則編譯錯誤。本文示範錯誤案例、正確語法、並延伸至 const 成員初始化與普通成員的初始化清單用法。
class Animal {
public:
Animal(int height, int weight) { cout << "animal construct\n"; }
~Animal() { cout << "animal destruct\n"; }
// 無 Animal() 預設建構函數
};
class Fish : public Animal {
public:
Fish() { cout << "fish construct\n"; } // 錯誤:隱式呼叫 Animal() 失敗
};
error C2512: 'Animal' : no appropriate default constructor available
原因:Fish() 隱式嘗試呼叫 Animal(),但基類未定義無參數版本。
class Fish : public Animal {
public:
Fish() : Animal(400, 300) { // 冒號 + 基類建構函數(實引數)
cout << "fish construct\n";
}
~Fish() { cout << "fish destruct\n"; }
};
Derived() : Base(arg1, arg2), member1(val1), member2(val2) {
// 建構函數本體
}
class Point {
const int x; // 必須初始化
const int y;
int& ref; // 參考成員,必須綁定既有物件
public:
Point(int a, int b, int& r) : x(a), y(b), ref(r) {}
};
**唯一管道**:const、reference 成員**無法在建構函數本體賦值**,只能在初始化清單初始化。
class Fish : public Animal {
string name_;
int age_;
public:
Fish() : Animal(400,300), name_("Nemo"), age_(1) {} // 效率優於本體賦值
};
const/reference/無預設建構函數的類別成員 強制使用。| 錯誤寫法 | 問題 | 正確寫法 |
|---|---|---|
Fish() { Animal(400,300); } | 本體呼叫建立**暫時物件**,不初始化基類子物件 | Fish() : Animal(400,300) {} |
Fish(int h, int w) { Animal(h,w); } | 同左 | Fish(int h, int w) : Animal(h,w) {} |
Fish() : Animal() {} | 基類無預設建構函數 | 傳遞實際參數 : Animal(h,w) |
| 成員初始化順序與宣告順序不符 | 實際按宣告順序初始化,清單順序僅影響讀性 | 清單順序 = 宣告順序 |
基類無預設建構函數時,衍生類**必須**在初始化清單顯式呼叫 Base(args)。此語法同時也是初始化 const、reference、無預設建構函數成員的**唯一合法管道**。養成「所有成員皆在初始化清單初始化」習慣,效率最高、最安全、最符合 C++ 現代風格。