天天看點

Effective C++ 筆記(2):盡量以const,enum,inline替換#define條款二(clause 2)

條款二(clause 2)

盡量使用const,enum,inline替換#define(以編譯器替換預處理器)

1、使用const替換#define

通常替換

#define NUM 3.14           

const double Num = 3.14;//大寫名稱用于宏,這裡改變寫法           

其中有兩種特殊情況:

1、定義常量指針(往往放在頭檔案中)兩種寫法:

const char* const authorName = "Scott Meyers";
const std::string authorName("Scott Meyers");           

保證指針指向和指針指向的變量不會變。

2、class專屬常量:為了讓常量的作用域限制于class,通常采取這樣的方式:

class GamePlayer{
private:
    static const int Numbers = 5;
    int scores[Numbers];
};           

上述代碼在C++中編譯通過,但是我們通常說Class定義在頭檔案中,是以class中的成員“定義”通常稱之為聲明,這與标準定義是不相同的,如果想取某個class專屬常量的位址,或者編譯器不通過(非要你定義這個成員才行),這樣你需要在實作檔案中定義:

const int Gameplayer::Numbers;           

但在我的編譯器中加上這句會導緻編譯錯誤,因為編譯器要求const常量在定義時必須規定好數值。

當然,無法利用#define建立class專屬常量,因為#define不重視作用域。

如果你的編譯器比較舊不支援上述的文法則這樣寫:

class CostEstimate{
private:
    static const double Factor;
};

const double CostEstimate::Factor = 1.35;           

2、或者用enum hack

class GamePlayer{
private:
//    static const int Numbers = 5;
    enum {Numbers = 5};
    int scores[Numbers];
};           

也可以編譯通過。

取const得位址是合法的,取enum和#define的位址通常不合法,如果不想别人通過指針或者引用擷取你的某個整數的位址,那麼enum可以實作你的想法。另外enum和#define一樣不會導緻非必要的記憶體配置設定。

3、不用宏實作函數

别用這種函數

#define CALL_WITH_MAX(a, b) F((a) > (b) ? (a): (b))           

使用

template <typename T>
inline void callWithMax(const T& a,const T& b)
{
    f(a > b ? a : b); //f為簡單比較函數
}           

這種寫法有很多好處,它遵守作用域和通路規則。

雖然我們對預處理器的要求變低了,但#define和#include依然是必需品。

繼續閱讀