建構函數是 C++ 類別自動初始化的核心機制。本文透過實例演示:未初始化成員變數導致隨機值、手動 init() 易忘記呼叫、建構函數自動執行初始化、編譯器提供預設建構函數的三大條件,並引用 ANSI C++ ISO 標準釐清常見誤區。
#include
using namespace std;
class Point {
public:
int x, y;
void output() { cout << x << endl << y << endl; }
};
int main() {
Point pt; // 未初始化
pt.output(); // 輸出兩個巨大隨機負數 (堆疊殘留值)
}
原因:pt 建立時,編譯器只配置記憶體,不自動清零。成員 x, y 含隨機位元模式。
class Point {
public:
int x, y;
void init() { x = 0; y = 0; }
void output() { cout << x << endl << y << endl; }
};
int main() {
Point pt;
pt.init(); // 程式設計師必須記得呼叫
pt.output(); // 輸出 0, 0
}
缺點:易忘記呼叫、無法保證物件一出生即處於合法狀態。
class Point {
public:
int x, y;
Point() { // 建構函數:無回傳型別、名稱與類別同名
x = 0; y = 0;
}
void output() { cout << x << endl << y << endl; }
};
int main() {
Point pt; // 自動呼叫 Point::Point()
pt.output(); // 保證輸出 0, 0
}
特性:
void 都不能寫)。若類別**未宣告任何建構函數**,編譯器**僅在下列三種情況**合成預設建構函數:
除此之外 (如純資料類別 struct A { int x; };),**編譯器不合成**預設建構函數,物件行為同 malloc 未初始化記憶體。
class Point {
public:
Point(int a, int b) { x = a; y = b; } // 使用者定義帶參數建構函數
int x, y;
};
int main() {
Point pt; // 編譯錯誤:無預設建構函數
Point pt2(1,2); // OK
}
對策:若需無參數建構,必須**額外定義** Point() { x=0; y=0; }。
Point(int a, int b) : x(a), y(b) {} 效率更高、可初始化 const/reference 成員。explicit 防止隱含轉換。Point() : Point(0,0) {} 避免重複程式碼。Point(int a=0, int b=0) 合併無參與帶參版本。建構函數是 C++ 保證物件「生而有效」的關鍵。理解編譯器合成預設建構函數的**三大條件**,能避免「以為有預設建構函數實則無」的編譯/執行期錯誤。善用初始化清單、explicit、委派建構,寫出高效、安全的 C++ 程式碼。