01 C++還有搞頭嗎??
02 常量??
不變的值更易于理解、跟蹤和分析,所以應該盡可能地使用常量代替變量,定義值的時候,應該把?const?作為默認的選項。
使用?const?常量取代宏
說明:宏是簡單的文本替換,在預處理階段時完成,運行報錯時直接報相應的值;跟蹤調試時也是顯示值,而不是宏名;宏沒有類型檢查,不安全;宏沒有作用域。
示例:
#define?MAX_MSISDN_LEN (20)?//不好的例子const?int?MAX_MSISDN_LEN =?20;?//好的例子
03??
一組相關的整型常量應定義為枚舉
說明:之所以使用枚舉,基于:
??
枚舉比#define?或 const int 更安全,因為編譯器會檢查參數值是否是否位于枚舉取值范圍內,從而避免錯誤發生。
示例:
//好的例子:enum?DayOfWeek{sunday,monday, tuesday, wednesday, thursday, friday, saturday}; ?enum?Color{black, blue, white, red, purple}; ?BOOL?ColorizeCalendar(DayOfWeek today, Color todaysColor); ?ColorizeCalendar(blue, sunday);?//編譯報錯,Blue和Sunday位置錯誤//不好的例子: ?const?int?sunday =?0; ?const?int?monday =?1; ?const?int?black =?0; ?const?int?blue =?1; ?BOOL?ColorizeCalendar(int?today,?int?todaysColor); ?ColorizeCalendar(blue, sunday);?//不會報錯
??
當枚舉值需要對應到具體數值時,須在聲明時顯示賦值。否則不需要顯式賦值,以避免重復賦值,降低維護(增加、刪除成員)工作量。
示例:
//好的例子:S協議里定義的設備ID值,用于標識設備類型enum?TDeviceType ?{ ?DEV_UNKNOWN =?-1, ?DEV_DSMP =?0, ?DEV_ISMG =?1, ?DEV_WAPPORTAL =?2??};//好的例子:程序中用來標識會話狀態的枚舉定義enum?TSessionState ?{ ?SESSION_STATE_INIT, ?SESSION_STATE_CLOSED, ?SESSION_STATE_WAITING_FOR_RSP ?};
??
應當盡量避免枚舉值重復,如必須重復也要用已定義的枚舉來修飾,例如:
typedef enum ?{ ?RTCP_SR = 200, ?RTCP_MIN_TYPE = RTCP_SR, //must be lowest known type ?RTCP_RR = 201,RTCP_SDES = 202, ?RTCP_BYE = 203, ?RTCP_APP = 204, ?RTCP_RTPFB = 205, ?RTCP_PSFB = 206, ?RTCP_XR = 207, ?RTCP_RSI = 208, ?RTCP_PUBPORTS = 209, ?RTCP_MAX_TYPE = RTCP_PUBPORTS //must be highest known?} rtcp_type_t;
04??
不相關的常量,即使取值一樣,也必須分別定義
說明:一個常量只用來表示一個特定功能,即一個常量不能有多種用途。
示例:
//好的例子:協議A和協議B,手機號(MSISDN)的長度都是20。unsigned?const?int?A_MAX_MSISDN_LEN =?20;?unsigned?const?int?B_MAX_MSISDN_LEN =?20;?//或者使用不同的名字空間:namespace?alib?{?const?int?MAX_MSISDN_LEN =?20;?}?namespace?blib?{?const?int?MAX_MSISDN_LEN =?20;?}
05??
盡可能使用 const
說明:
在聲明的變量或參數前加上關鍵字 const 用于指明變量值不可被篡改。
類成員函數加上 const?限定符表明該函數不會修改類成員變量的狀態。
使用 const 常見的場景:
??函數參數:傳遞引用時,如果函數不會修改傳入參數, 該形參應聲明為 const。
void printValue(const int& value) { // 正確:不需要修改valuestd::cout << value << std::endl;// value = 10; // 錯誤:不能修改const參數
}
int main() {int x = 5;const int y = 10;printValue(x); // 可以傳遞非const變量printValue(y); // 可以傳遞const變量printValue(42); // 可以傳遞臨時值return 0;
}
??成員函數:訪問函數(如 get 函數);不修改任何數據成員的函數;未調用非 const 函數、未返回數據成員的非 const 指針或引用的函數。
class MyClass {private:int value;mutable int cache; // 即使在const函數中也可以修改mutable bool cacheValid;public:MyClass(int v) : value(v), cache(0), cacheValid(false) {}// 正確的const成員函數示例int getValue() const {return value; // 只讀取,不修改}int getValueWithCache() const {if (!cacheValid) {cache = value * 2; // 修改mutable成員是允許的cacheValid = true;}return cache;}// 錯誤示例:這個函數修改了數據成員,不能是constvoid setValue(int v) {value = v;}// 錯誤示例:這個函數調用了非const成員函數,不能是constvoid updateAndGetValue() const {setValue(10); // 錯誤:不能在const函數中調用非const函數}// 錯誤示例:返回了非const引用,不能是constint& getValueRef() const {return value; // 錯誤:返回了非const引用}// 正確示例:返回const引用const int& getValueRef() const {return value; // 正確:返回const引用}};int main() {const MyClass obj(5);int val = obj.getValue(); // 正確:可以在const對象上調用const成員函數// obj.setValue(10); // 錯誤:不能在const對象上調用非const成員函數return 0;}
??數據成員:如果數據成員在對象構造之后不再發生變化, 可將其定義為 const。
class Circle {private:const double radius; // 半徑在構造后不應改變const double pi; // π值恒定不變double x, y; // 位置可以改變public:Circle(double r, double x, double y): radius(r), pi(3.141592653589793), x(x), y(y) {// 在構造函數初始化列表中初始化const成員}double getArea() const {return pi * radius * radius; // 可以使用const成員}void move(double newX, double newY) {x = newX; // 可以修改非const成員y = newY;}// 錯誤示例:試圖修改const成員void setRadius(double newRadius) {// radius = newRadius; // 錯誤:不能修改const成員}};int main() {Circle c(5.0, 0.0, 0.0);double area = c.getArea(); // 正確:可以訪問const成員// c.radius = 10.0; // 錯誤:不能修改const成員return 0;}class Circle {private:const double radius; // 半徑在構造后不應改變const double pi; // π值恒定不變double x, y; // 位置可以改變public:Circle(double r, double x, double y): radius(r), pi(3.141592653589793), x(x), y(y) {// 在構造函數初始化列表中初始化const成員}double getArea() const {return pi * radius * radius; // 可以使用const成員}void move(double newX, double newY) {x = newX; // 可以修改非const成員y = newY;}// 錯誤示例:試圖修改const成員void setRadius(double newRadius) {// radius = newRadius; // 錯誤:不能修改const成員}};int main() {Circle c(5.0, 0.0, 0.0);double area = c.getArea(); // 正確:可以訪問const成員// c.radius = 10.0; // 錯誤:不能修改const成員return 0;}