建構函式、解構函式、指派函式是每個類別最基礎的成員函式。它們平凡到讓人容易掉以輕心,實則如同「沒有蓋子的下水道」般危險。每個類別僅有一個解構函式和一個指派函式,但可擁有多個建構函式(含一個複製建構函式)。
若程式設計師不主動撰寫,C++ 編譯器會自動生成四個預設版本:
A(); // 預設無參數建構函式
A(const A& a); // 預設複製建構函式
~A(); // 預設解構函式
A& operator=(const A& a); // 預設指派函式
若有人宣稱撰寫這三大函式「很簡單、不用動腦」,其認識顯然尚淺,功力有待精進。
本章以 String 類別為例,深入剖析常被教科書忽略的關鍵細節:
class String {
public:
String(const char* str = NULL); // 一般建構函式
String(const String& other); // 複製建構函式
~String(); // 解構函式
String& operator=(const String& other); // 指派函式
private:
char* m_data; // 動態配置的字串緩衝區
};
C++ 編譯器具備嚴格的型別安全檢查,能找出大多數語法錯誤。但「通過編譯 ≠ 無錯誤」。經驗顯示,許多難以察覺的 Bug 源於變數未正確初始化或清理,而這兩項工作極易被遺忘。
Stroustrup 的解決方案極具智慧:
如此便不必擔心遺忘初始化與清理。
~ 前綴,象徵「相反操作」。void)。它們的使命單純如「出生與死亡」,若有回傳值編譯器將無所適從。(參考文獻:Eckel, Thinking in C++, pp. 55-56)