當需要在**類範圍內** (而非對象範圍) 共享數據或提供無狀態操作時,使用 static 修飾成員變量/函數。本文詳細講解聲明/定義分離規則、初始化時機、訪問方式、與非靜態成員的交互限制、線程安全模式、單例實現、C++17 inline static 現代寫法。
| 特性 | 靜態數據成員 | 靜態成員函數 |
|---|---|---|
| 屬於 | 類 (單份拷貝) | 類 (無 this 指針) |
| 存儲區 | 全局/靜態存儲區 | 代碼段 |
| 聲明位置 | 類內 static Type name; | 類內 static Ret Func(Args); |
| 定義位置 | **類外** Type Class::name = init; (C++17 前) | 類外 Ret Class::Func(Args) { ... } |
| C++17 類內定義 | static inline Type name = init; | 同左 (函數體可類內定義) |
| 訪問方式 | Class::name / obj.name (不推薦後者) | Class::Func() / obj.Func() |
| 可訪問成員 | 無限制 | **僅靜態成員** (無 this) |
| 可聲明 cv/虛 | 不可 | 不可 const/volatile/virtual |
#include
#include
#include
using namespace std;
class Internet {
string name_, addr_;
static inline int s_count = 0; // C++17 inline static 定義+初始化
static inline mutex s_mtx; // 線程安全鎖
public:
Internet(const string& n, const string& a) : name_(n), addr_(a) {
lock_guard lk(s_mtx);
++s_count;
}
~Internet() {
lock_guard lk(s_mtx);
--s_count;
}
// 靜態成員函數:獲取當前存活對象數
static int GetLiveCount() {
lock_guard lk(s_mtx);
return s_count;
}
// 靜態工廠方法:統一創建邏輯
static shared_ptr Create(const string& n, const string& a) {
return make_shared(n, a);
}
void Print() const { cout << name_ << " | " << addr_ << endl; }
};
int main() {
cout << "Initial: " << Internet::GetLiveCount() << endl; // 0
{
auto a = Internet::Create("Lab", "cndev-lab.com");
auto b = Internet::Create("Test", "test.com");
cout << "In scope: " << Internet::GetLiveCount() << endl; // 2
} // a,b 析構
cout << "After scope: " << Internet::GetLiveCount() << endl; // 0
}
| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
class A { static int x = 0; }; | 類內初始化非 const 整型靜態成員 (C++17 前非法) | 類外定義 `int A::x = 0;` 或 C++17 `static inline int x = 0;` |
static void Foo() { this->bar(); } | 靜態函數使用 this | 移除 this,改訪問靜態成員或傳入對象引用 |
static virtual void Bar(); | 靜態虛函數非法 | 去掉 static 或 virtual |
obj.StaticFunc(); | 雖合法但誤導 — 看起來像調用對象方法 | 統一用 Class::StaticFunc() 強調類級語義 |
| 跨 DLL 共享靜態計數器 | 各模塊獨立拷貝,計數不一致 | 導出函數訪問單例/共享內存/註冊表/數據庫 |
class Singleton {
Singleton() = default;
~Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& Instance() {
static Singleton instance; // C++11 線程安全、延遲初始化
return instance;
}
void DoSomething() { /* ... */ }
};
// 使用
Singleton::Instance().DoSomething();
class Modern {
static inline int s_counter = 0; // 類內定義+初始化,無需 cpp 文件
static inline string s_tag = "default"; // 任意類型,含類類型
static inline vector s_cache; // 容器自動默認構造
public:
static inline void Reset() { s_counter = 0; s_cache.clear(); }
static inline int Count() { return s_counter; }
};
**優勢**:頭文件唯一定義、無 ODR 風險、模板友好、編譯期常量傳播優化。新項目**全面採用**。
靜態成員是「類級全局變量」的類型安全、封裝化形式。善用 `inline static`、Meyers Singleton、線程安全初始化,能優雅解決共享狀態、工廠方法、註冊表、緩存池等類級需求。