第一篇:儘量多的以 const/enum/inline 替代 #define

穆晨發表於2017-01-27

前言

       在程式導向語言,如 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 並沒有徹底退出舞臺,它提供的條件編譯功能目前也是非常實用的。

相關文章