朋友實作單例類別 CSingleton,建構子設為 private,提供靜態 GetInstance() 回傳唯一實例參考。但以下程式碼編譯失敗:
CSingleton temp = CSingleton::GetInstance(); // 編譯錯誤
當編譯器遇到上述語句,會尋找拷貝建構子 CSingleton(const CSingleton&)。若使用者未自行宣告,編譯器會隱式產生 public 預設拷貝建構子(逐位元複製),導致單例保護機制失效。
為徹底禁止複製,必須顯式宣告並設為 private:
class CSingleton {
public:
static CSingleton& GetInstance() {
static CSingleton theInstance; // 唯一實例,區域靜態變數確保執行緒安全 (C++11 起)
return theInstance;
}
protected:
CSingleton() {} // 預設建構子,protected 允許繼承
private:
// 關鍵:禁止複製與賦值
CSingleton(const CSingleton&); // 僅宣告,不定義(或定義為 ASSERT(FALSE))
CSingleton& operator=(const CSingleton&); // 僅宣告,不定義
};
class CSingleton {
public:
static CSingleton& GetInstance() {
static CSingleton theInstance;
return theInstance;
}
protected:
CSingleton() {} // 需有預設建構子以建立實例
private:
CSingleton(const CSingleton&) {} // 私有拷貝建構子
CSingleton& operator=(const CSingleton&) {} // 私有賦值運算子
};
int main() {
// 以下皆編譯錯誤(私有拷貝/賦值)
// CSingleton x = CSingleton::GetInstance(); // error
// CSingleton y = CSingleton::GetInstance(); // error
// x = y; // error
// 正確用法:指標或參考
CSingleton* p1 = &CSingleton::GetInstance();
CSingleton* p2 = &CSingleton::GetInstance();
CSingleton& ref = CSingleton::GetInstance();
return 0;
}
private (或 protected 允許繼承)static GetInstance() 回傳唯一實例參考/指標static 變數確保延遲初始化與執行緒安全 (C++11 保證)protected,但拷貝/賦值仍需 private= delete 明確刪除:CSingleton(const CSingleton&) = delete;正確實作單例模式的關鍵在於顯式封鎖所有複製路徑。理解編譯器隱式行為,才能寫出真正強健的單例類別。