單例模式確保類全局僅有一實例並提供訪問點。C++ 中常用 Meyers Singleton (函數內靜態變量) 實現線程安全 (C++11 保證) 的單例。本文提供兩個巨集,將單例樣板代碼封裝為一鍵引入,區別在於是否預設實現無參構造函數,並展示實際類整合範例。
#define SINGLETON_CLASS_NO_DEF_CONSTRUCT_BODY(class_name) \
private: \
class_name(); \
class_name(const class_name&); \
class_name& operator=(const class_name&); \
public: \
static class_name& Instance() { \
static class_name one; \
return one; \
}
特點:聲明私有構造/拷買/賦值,**不提供定義**,強制使用者在 `.cpp` 中實現構造函數。
#define SINGLETON_CLASS(class_name) \
private: \
class_name() {} \
class_name(const class_name&); \
class_name& operator=(const class_name&); \
public: \
static class_name& Instance() { \
static class_name one; \
return one; \
}
特點:內聯定義空構造函數 `class_name() {}`,使用者**無需**在 `.cpp` 實現構造。
#ifndef HOST_BASIC_INFORMATION_H
#define HOST_BASIC_INFORMATION_H
#include
class HostBasicInformation {
// 引入無預設構造版巨集
SINGLETON_CLASS_NO_DEF_CONSTRUCT_BODY(HostBasicInformation)
public:
virtual ~HostBasicInformation();
std::string GetInstallCode();
// 其他業務方法...
};
#endif // HOST_BASIC_INFORMATION_H
#include "HostBasicInformation.h"
// 必須實現構造函數 (巨集僅聲明)
HostBasicInformation::HostBasicInformation() {
// 初始化邏輯:讀取註冊表、硬體資訊、生成安裝碼等
}
HostBasicInformation::~HostBasicInformation() {
// 清理資源
}
std::string HostBasicInformation::GetInstallCode() {
return "INSTALL_CODE_12345"; // 實際業務邏輯
}
#include "HostBasicInformation.h"
void someFunction() {
// 獲取單例引用並調用方法
std::string code = HostBasicInformation::Instance().GetInstallCode();
// 等價於:
// HostBasicInformation &inst = HostBasicInformation::Instance();
// std::string code = inst.GetInstallCode();
}
| 優點 | 缺點/風險 |
|---|---|
| 極度簡化聲明,一鍵引入完整單例骨架 | 巨集無作用域,污染全局命名空間 |
| 強制統一實現風格,防止手寫疏漏 (如忘記私有化構造) | 調試困難:編譯器報錯指向巨集展開行,非邏輯源頭 |
| 編譯期展開,零運行開銷 | 模板/CRTP 方案類型安全性更高,支援繼承鏈單例 |
| 適配舊標準 (C++98/03) 專案 | 現代 C++ (C++17) 推薦內聯靜態成員變量 + `delete` 拷貝 |
class ModernSingleton {
private:
ModernSingleton() = default;
~ModernSingleton() = default;
ModernSingleton(const ModernSingleton&) = delete;
ModernSingleton& operator=(const ModernSingleton&) = delete;
public:
static ModernSingleton& Instance() {
static ModernSingleton instance;
return instance;
}
void DoSomething() { /* ... */ }
};
// 使用
ModernSingleton::Instance().DoSomething();
優勢:無巨集、編譯器完整類型檢查、支援繼承 (CRTP 模式)、IDE 重構友好。
巨集單例是特定歷史階段的產物,理解其原理有助於閱讀舊代碼,但現代 C++ 開發應優先選擇類型安全、工具友好的原生語法實現。