static 作用於類成員時,賦予其「屬於類而非對象」的語義:全程序僅有一份拷貝,無需實例化對象即可訪問。本文系統講解靜態數據成員、靜態成員函數的聲明定義規則、初始化位置、訪問方式,並對比非靜態成員差異。
class A {
static int m_a; // 類內聲明(不可初始化,C++17 前非整型 const 也不可)
int m_b; // 非靜態成員
public:
void set(int i, int j) { m_a = i; m_b = j; }
void show() const;
};
// 類外定義(必須,分配內存)
int A::m_a; // 可在此處初始化:int A::m_a = 123;
為什麼要分離? 類定義只是聲明類型,不分配存儲;靜態成員屬於類,需在全局/命名空間作用域定義分配內存(類似全局變量但有作用域限制)。
int A::m_a = 123;(通用,推薦)static inline int m_a = 123;(inline 關鍵字避免多重定義)static const int MAX = 100;,但若需取地址仍需類外定義
A a1, a2;
a1.set(11, 22);
a1.show(); // 輸出 靜態:11, 非靜態:22
a2.set(33, 44);
a2.show(); // 輸出 靜態:33, 非靜態:44 → 靜態成員被修改,a1 也受影響
a1.show(); // 輸出 靜態:33, 非靜態:22 → 驗證共享性
// 類名訪問(需 public)
A::m_a = 100; // 直接通過類訪問,無需對象
A::show(); // 錯誤:非靜態成員函數需對象調用
| 特性 | 靜態成員 | 非靜態成員 |
|---|---|---|
| 內存分配 | 全局/靜態存儲區,僅一份 | 每個對象獨有,隨對象創建/銷毀 |
| 聲明位置 | 類內聲明 + 類外定義 | 僅類內聲明 |
| 初始化 | 類外定義處 / C++17 inline | 構造函數初始化列表 |
| 訪問方式 | 對象. / 對象-> / 類名:: | 僅 對象. / 對象-> |
| this 指針 | 無 | 隱含 this |
| 可為 const | 可 | 可 |
class A {
static int m_count;
public:
static void showCount() { // 類內定義隱含 inline
cout << "Count: " << m_count << endl;
// m_b = 10; // 錯誤:無 this,不能訪問非靜態成員
}
static int getCount(); // 類外定義
};
int A::getCount() { return m_count; } // 類外定義不加 static
核心限制: 靜態成員函數沒有 this 指針,因此:
const、volatile、virtual
A::showCount(); // 類名訪問(推薦,語義清晰)
a1.showCount(); // 對象訪問(合法但誤導,看起來像依賴對象)
class ObjectTracker {
static inline int s_count = 0; // C++17
public:
ObjectTracker() { ++s_count; }
~ObjectTracker() { --s_count; }
static int liveCount() { return s_count; }
};
class Singleton {
static Singleton* s_instance;
Singleton() = default;
public:
static Singleton* instance() {
if (!s_instance) s_instance = new Singleton;
return s_instance;
}
};
Singleton* Singleton::s_instance = nullptr;
class Config {
public:
static const int MAX_CONNECTIONS = 1000;
static const char* DEFAULT_HOST; // 類外定義
};
const char* Config::DEFAULT_HOST = "127.0.0.1";
class Logger {
public:
static Logger& get() {
static Logger instance; // C++11 線程安全局部靜態
return instance;
}
private:
Logger() {}
};
unresolved external symbolinline 解決)static inline (C++17) 簡化定義std::mutex、std::atomic)靜態成員打破了「數據隨對象而生」的常規,提供了類級別的共享狀態與無對象操作能力。掌握「聲明在類內、定義在類外、無 this 指針、類名訪問」四大核心特徵,即可靈活運用於資源管理、模式實現、配置共享等場景。