前言
在程式導向語言,如 C 語言中,#define 非常常見,也確實好用,值得提倡。但在如今物件導向的語言,如 C++ 語言中,#define 就要儘量少用了。
為何在 C++ 中就要少用了呢?
這是因為 #define 機制只是簡單的字元替換,這樣一方面你無法對 #define 定義的東西加入一些C++語法元素,因此限制了物件導向程式語言的威力;
另一方面編譯器不能獲取到你所定義的變數型別/函式型別,因此無法提供全面的檢測機制,導致隱藏 bug 增多。
所以要想出對 #define 機制進行替代的思路。
思路一:使用類變數代替巨集全域性變數
步驟:
1. 在類定義式內宣告 static 成員
2. 在類的實現檔案內初始化該成員
3. 由該類派生出的任何物件都可以訪問這個成員。
示例程式碼:
1 #include <iostream> 2 3 using namespace std; 4 5 class CA 6 { 7 public: 8 static const float a; 9 }; 10 11 const float CA::a = 5.0; 12 13 int main () 14 { 15 cout << CA::a << endl; 16 17 cin.get(); 18 19 return 0; 20 }
思路二:類定義中就要用到的全域性常量使用 enum 實現
在思路一中,如果類 CA 要使用到 a,比如類中要宣告一個陣列,則下面語句是非法的:int arrayA[a];。為啥?因為在類定義的標頭檔案中,編譯器還獲取不到 a 的具體值。因此,可以採用所謂的 the enum hack 做法來解決這個問題。
1 enum { ArrayNum=5 }; 2 int array[ArrayNum];
思路三:採用 template inline 函式代替巨集函式
前處理器的一個很重要的功能是實現巨集函式,如下面這個巨集函式能夠返回 a 和 b 之間較大的值而不論a 和 b的具體型別:
1 #define CALL_WITH_MAX(a, b) f((a)>(b)?(a):(b))
但這樣的實現有好幾個漏洞,讀者不放試著自己找出來。
而採用 template inline 函式不單沒有這些漏洞,還可以給它新增各種語法機制,比如將它定義為某個類的成員函式。下面的程式碼演示了 template inline 函式實現改功能的具體做法:
1 template <typename T> 2 inline void callWithMax (const T &a, const T &b) 3 { 4 f(a>b?a:b); 5 }
小結
這三個思路在很多時候都可以替換掉 #define。
然而,#define 並沒有徹底退出舞臺,它提供的條件編譯功能目前也是非常實用的。