建構函式是類別的特殊成員函式,名稱與類別相同、無回傳型別,在物件建立時自動呼叫,用於初始化成員變數。
class Student {
public:
Student() { number = 1; score = 100; } // 自動初始化
void show() { cout << number << endl << score << endl; }
protected:
int number, score;
};
int main() { Student a; a.show(); } // 輸出 1, 100
class Teacher {
public:
Teacher(const char* input_name) {
name = new char[10];
strcpy(name, input_name); // 深層複製,避免指標指向堆疊
}
Teacher() {} // 若需無參數建構,必須額外定義(多載)
void show() { cout << name << endl; }
~Teacher() { delete[] name; } // 釋放動態記憶體
protected:
char* name;
};
int main() {
Teacher a("test"); // 呼叫帶參數建構函式
// Teacher b; // 錯誤:無無參數建構函式
a.show();
}
關鍵點: name = input_name; 僅複製指標值,導致解構時 delete 錯誤記憶體區塊,必須配置堆疊空間並 strcpy。
若類別成員為另一類別物件,建構外層物件時會自動呼叫成員物件的建構函式。
class Teacher { // 內層類別
public:
Teacher() { director = new char[10]; strcpy(director, "王大力"); }
~Teacher() { delete[] director; }
char* show() { return director; }
protected:
char* director;
};
class Student { // 外層類別
public:
Student() { number = 1; score = 100; }
void show() { cout << teacher.show() << endl << number << endl << score << endl; }
protected:
int number, score;
Teacher teacher; // 成員物件
};
int main() {
Student a; a.show(); // 自動呼叫 Teacher()
Student b[5]; // 陣列每個元素皆自動呼叫 Teacher()
}
解構函式名稱為 ~類別名(),無參數、無回傳值、不可多載,在物件生命週期結束時自動呼叫,用於釋放資源(動態記憶體、檔案控制代碼、Socket 等)。
class Teacher {
public:
Teacher() { director = new char[10]; strcpy(director, "王大力"); }
~Teacher() { cout << "釋放堆疊 director 1 次"; delete[] director; cin.get(); }
char* show() { return director; }
protected:
char* director;
};
// 執行時會在 main 結束前印出 6 次釋放訊息(1 個 a + 5 個 b[5])
若成員物件只有帶參數建構函式,無法在類別定義內直接傳參,必須使用初始化清單(冒號語法)。
class Student {
Teacher teacher("王大力"); // 編譯錯誤:類別定義非物件,無法傳參
};
class Student {
public:
Student(const char* temp) : teacher(temp) { // 冒號後指定呼叫 teacher 的建構函式
number = 1; score = 100;
}
protected:
int number, score;
Teacher teacher;
};
int main() { Student a("王大力"); a.show(); }
可同時初始化多個成員、const 常數成員、參考成員:
class Student {
public:
Student(const char* temp, int& pk) : teacher(temp), pk(pk), ps(10) {
number = 1; score = 100;
}
protected:
Teacher teacher;
int& pk; // 參考成員
const int ps; // 常數成員
int number, score;
};
int main() {
char* t_name = "王大力";
int b = 99;
Student a(t_name, b); // pk 綁定 b,ps 初始化為 10
}
注意: 初始化清單中 pk(pk) 為參考綁定,非函式呼叫;ps(10) 為常數初始化。C++ 允許 int a(10) 等同 int a = 10,但清單中只能用括號不能用等號。
main() 之前建構;函式內 static 物件僅首次呼叫時建構一次。class Test {
public:
Test(int j) : pb(j), pa(pb + 5) {} // 看似 pa=15
public:
int pa; // 先宣告
int pb; // 後宣告
};
int main() {
Test a(10);
cout << a.pa << endl; // 輸出亂碼!因為 pa 先建構,此時 pb 尚未初始化
cout << a.pb << endl; // 10
}
修正: 調整宣告順序 int pb; int pa;,或在建構函式本體內賦值 pa = pb + 5;。
=delete 禁用),避免淺層複製導致雙重釋放。