特殊成員函數,與類別同名,無回傳型別(連 void 也不可),物件建立時自動呼叫,完成初始化職責。
class Student {
const char* m_name;
int m_age;
float m_score;
public:
Student(const char* name, int age, float score); // 宣告
void show() const;
};
Student::Student(const char* name, int age, float score)
: m_name(name), m_age(age), m_score(score) { } // 定義
int main() {
Student stu("小明", 15, 92.5f); // 棧上:參數跟在物件名後
Student* p = new Student("李華", 16, 96); // 堆上:參數跟在類別名後
stu.show(); p->show();
delete p;
return 0;
}
必須為 public,否則無法建立物件(private/protected 僅用於單例/工廠等進階模式)。
class Student {
const char* m_name;
int m_age;
float m_score;
public:
Student(); // 預設建構
Student(const char* name, int age, float score); // 完整初始化
void setName(const char* name);
void setAge(int age);
void setScore(float score);
void show() const;
};
Student::Student() : m_name(nullptr), m_age(0), m_score(0.0f) { }
Student::Student(const char* name, int age, float score)
: m_name(name), m_age(age), m_score(score) { }
Student stu; 或 new Student 僅在存在零參數建構函數時合法。Student() { }(空函數體)。Student s1; // OK:呼叫 Student()
Student s2(); // 錯誤:被解析為函數宣告!
Student* p1 = new Student; // OK
Student* p2 = new Student(); // OK
陷阱:Student s2(); 宣告一個回傳 Student 的函數,而非建立物件。棧上建立物件**不可加括號**,堆上則可加可不加。
class IntArray {
int* m_data;
int m_size;
public:
IntArray(int size) : m_size(size) {
m_data = (size > 0) ? new int[size] : nullptr;
}
~IntArray() { delete[] m_data; }
int& operator[](int i) { return m_data[i]; }
int size() const { return m_size; }
};
建構函數配置資源,析構函數釋放資源,物件生命週期綁定資源生命週期,這是 C++ 資源管理的核心範式。
| 錯誤 | 後果 | 修正 |
|---|---|---|
| 建構函數回傳值 | 編譯錯誤 | 移除回傳型別 |
主體內 return value; | 編譯錯誤 | 建構函數不可回傳值 |
| 未定義建構函數卻傳參建立物件 | 編譯錯誤 | 提供對應參數的建構函數 |
| 定義建構函數後預期編譯器仍提供預設版本 | 無參數建立物件失敗 | 手動補上 Student() 或使用預設參數 |
Student s(); 以為建立物件 | 宣告函數 | 改為 Student s; |
建構函數是物件初始化的強制入口。掌握「重載多樣化初始化」、「預設建構函數合成規則」、「括號省略陷阱」,並配合初始化串列、RAII 模式,即能編寫安全、高效的 C++ 類別。