技術(shù)交流QQ群:1027579432阔挠,歡迎你的加入医舆!
1.盡量用const竭翠、enum振坚、inline代替宏#define
- 使用編譯器替換預處理器,或許#define可以不被視為C++語言中的一部分斋扰,如下面的代碼:
#define PI 3.14
- 名稱PI也行從來都沒有被編譯器看到過渡八,也許在編譯器開始處理源碼之前,它就已經(jīng)被預處理器移走了传货。于是屎鳍,PI有可能沒進入記號表中,所以導致當使用此常量但獲得一個編譯錯誤信息時问裕,可能會帶來困惑逮壁,因為這個錯誤也會會提到3.14而不是PI;如果PI被定義在一個不是自己寫的頭文件中粮宛,我們可能對3.14的含義一無所知窥淆。解決的方法是使用常量替換上面的宏,見下面的代碼
const double Pi = 3.14; // 宏名一般是大寫的
- 浮點常量Pi肯定會被編譯器看到巍杈,當然會進入記號表中忧饭。此外,使用浮點常量Pi將會比使用宏有較小的代碼量筷畦,因為使用宏時词裤,會盲目的將宏名稱PI替換成3.14,可能導致目標代碼出現(xiàn)多份的3.14鳖宾,但是使用浮點常量絕不會出現(xiàn)相同的情況吼砂。
2.使用常量代替宏#define的兩種特殊情況
- 2.1 定義常量指針
- 由于常量定義式通常被放在頭文件中,以便被不同的源碼所包含鼎文。因此渔肩,有必要將指針聲明為const。例如在頭文件中定義一個常量的char*-base字符串漂问,必須寫const兩次赖瞒。下面的情況使用string類的對象會比使用指向常量的常量指針更好。
const char* const authorName = "Curry_Coder"; // 指向常量的常量指針 const string authorName = "Curry_Coder";
- 由于常量定義式通常被放在頭文件中,以便被不同的源碼所包含鼎文。因此渔肩,有必要將指針聲明為const。例如在頭文件中定義一個常量的char*-base字符串漂问,必須寫const兩次赖瞒。下面的情況使用string類的對象會比使用指向常量的常量指針更好。
- 2.2 class的專屬常量
- 為了將常量的作用域限制在class中蚤假,必須將常量作為class中的一個成員栏饮,為了確保常量至多只有一份實體,必須讓常量成為靜態(tài)成員變量磷仰。無法使用#define創(chuàng)建一個class專屬常量袍嬉,因為#define并不重視作用域,一旦宏被定義后,它就在其后的編譯過程中有效伺通。這意味著#define不僅不能用來定義class專屬常量箍土,也不能提供任何的封裝,沒有訪問權(quán)限的限制罐监,但const成員變量是可以被封裝的吴藻。
class GamePlayer{ public: static const int NumTurns = 5; // 常量聲明 int scores[NumTurns]; };
- 當編譯器不允許使用static int class 常量來完成類內(nèi)部的初值設定時,可以使用所謂的enum hack補償?shù)淖龇ü匆粋€屬于枚舉類型的數(shù)值可以當做int類型使用沟堡,enum可以讓別人無法獲得一個指針或引用指向你的某個整數(shù)常量,如下面的例子:
class GamePlayers{ private: enum {NumTurns = 5}; int socres[NumTurns]; // TODO; };
- 為了將常量的作用域限制在class中蚤假,必須將常量作為class中的一個成員栏饮,為了確保常量至多只有一份實體,必須讓常量成為靜態(tài)成員變量磷仰。無法使用#define創(chuàng)建一個class專屬常量袍嬉,因為#define并不重視作用域,一旦宏被定義后,它就在其后的編譯過程中有效伺通。這意味著#define不僅不能用來定義class專屬常量箍土,也不能提供任何的封裝,沒有訪問權(quán)限的限制罐监,但const成員變量是可以被封裝的吴藻。
3.#define誤用的情況
- 宏看起來像函數(shù)矢空,但不會產(chǎn)生函數(shù)調(diào)用航罗,從而導致額外的開銷。下面是帶參數(shù)的宏屁药,調(diào)用函數(shù)f:
#define CALL_MAX(a, b) f((a) > (b) ? (a):(b))
- 上面的宏存在太多的缺點粥血,當寫出上面的宏時,必須記住為宏中的所有實參加上()酿箭,否則別人在表達式中調(diào)用這個宏時會帶來疑惑复亏。但有時候即使加上(),也會產(chǎn)生不可思議的事情:
int a = 5; b = 0; CALL_MAX(++a, b); // a被加2次 CALL_MAX(++a, b+10); // a被加1次
- 使用內(nèi)聯(lián)的函數(shù)模板解決上面的問題,函數(shù)模板接收兩個同類型的對象七问,并以其中較大者調(diào)用f蜓耻,不需要為參數(shù)加上括號茫舶,如下面的例子:
template<typename T> inline void call_max(const T &a, const T &b){ f(a > b) ? a:b; }
4.總結(jié)
- 對于單純的常量械巡,最好使用const對象會enum代替#define宏
- 對于類似于函數(shù)的宏,最好改用inline函數(shù)替換#define