預處理指令 #define 在編譯前進行文本替換,導致兩大缺陷:
ASPECT_RATIO),錯誤訊息只會顯示展開後的常數(如 1.653),調試極其困難。const 變數只有一份存儲。const全域或命名空間作用域:
const double AspectRatio = 1.653; // 取代 #define ASPECT_RATIO 1.653
類內常數(需為 static const 整型才能類內初始化):
class GamePlayer {
static const int NumTurns = 5; // 聲明
int scores[NumTurns]; // 使用
};
// 若需取地址,在 .cpp 中定義:
// const int GamePlayer::NumTurns;
enum (枚舉常數)當編譯器不支援類內 static const int 初始化,或為了防止取地址操作(枚舉值是右值,不能取址),可用 enum:
class GamePlayer {
enum { NumTurns = 5 }; // 編譯期常數,不佔用對象內存
int scores[NumTurns];
};
注意:不要對枚舉值取址(&NumTurns),會編譯錯誤。
inline 函數模板宏 #define MAX(a,b) ((a)>(b)?(a):(b)) 有副作用風險(如 MAX(++a, b) 導致 a 增加兩次)。用 inline + 模板完美解決:
template
inline const T& max(const T& a, const T& b) {
return a > b ? a : b;
}
| 場景 | 推薦替換 | 關鍵優勢 |
|---|---|---|
| 全域/命名空間常數 | const T name = value; | 進符號表、型別安全、單一存儲 |
| 類內整型常數(作為數組大小等) | static const int name = value; 或 enum { name = value }; | 編譯期常數、不佔對象內存、enum 防止取址 |
| 類內非整型常數 | static const T name; 類內聲明,.cpp 中定義初始化 | 符合 C++ 標準、單一存儲 |
| 類函數宏 | template | 無副作用、型別安全、內聯展開 |
「能用 const 就不用 #define;需要編譯期整型常數且不想被取址時用 enum;宏函數一律改為 inline 模板函數。」
遵循此原則可大幅提升代碼可維護性、調試體驗與型別安全性,是現代 C++ 開發的基礎功底。