條款1 盡量用const和inline而不用#define
>"盡量用編譯器而不用預處理"
Ex. #define ASPECT_R 1.653 編譯器永遠不會看到ASPECT_R這個符號名, 在源碼進入編譯器之前, 就被預處理程序去掉, ASPECT_R 不會被加入到符號列表中; 編譯報錯時, 報錯信息指向1.653, 讓程序員無法跟蹤錯誤;(這個問題也會出現在符號調試器中);
>Solution: 定義常量 const double ASPECT_R = 1.653; 常量定義一般是在頭文件中, 許多源文件會包含它; [me: 如果只是局部使用的常量應該放在cpp中]
Note 定義指針常量時要注意, 除了指針所指的類型定義成const, 指針也經常要定義成const; Ex. const char* const kName = "Scott";
定義類的常量, 把常量限制在類中, 為了保證常量只有一份拷貝, 把它定義為靜態成員:
123456 class GamePlayer {private: static const int NUM_TURNS = 5; // constant declaration (老的編譯器不接受靜態成員聲明時初始化) int scores[NUM_TURNS]; // use of constant...};
Note 如果上面只是NU_TURNS的聲明(沒有 '= 5'), 必須在類實現代碼中定義類的靜態成員: const int GamePlayer::NUM_TURNS = 5; // mandatory definition; goes in class impl. file;
[文中可能是寫反了, 頭文件中有了 '= 5'就已經是定義了, 不需要在cpp中再定義;]
Note 類內只允許初始化整數類型的靜態成員: int, bool, char...
Issue 必須在頭文件中定義靜態成員的情況: 當你的類需要用到這個類的常量時: e.g. GamePlayer::scores數組聲明(編譯時需要知道數組大小); [SIZE必須是靜態常量或枚舉數]
Solution 對於不支持頭文件定義靜態常量的編譯器, 借用enum, 當需要int類型時可以使用枚舉類型:
1234567 class GamePlayer {private: enum { NUM_TURNS = 5 }; // "the enum hack" — makes // NUM_TURNS a symbolic name for 5 int scores[NUM_TURNS]; //fine...}
#define 指令實現看起來像函數的宏, 但是不會導致函數的調用;
#define max(a,b) ((a) > (b) ? (a) : (b)) 要保證每個參數加上括號, 即使這樣還是會有預期外的情況:
123 int a = 5, b = 0;max(++a, b); // a 的值增加了2 次max(++a, b+10); // a 的值只增加了1 次
>根據值來決定max的運行;
使用內聯函數替代: inline int max(int a, int b) { return a > b ? a : b; }
使用模板來擴展int之外的類型:
123 template<class T>inline const T& max(const T& a, const T& b){ return a > b ? a : b; }
>模板產生一套函數, 每個函數比較兩個可以轉換成同種類型的對象, 返回大的;
Note 在使用模板寫max之類的通用函數前, 先檢查標准庫中是否已經存在;
const和inline減少了預處理的使用, 但是#include還不能缺少, #ifdef/#ifndef 在控制編譯的過程中也很重要;
條款2 盡量用<iostream>而不用<stdio.h>
scanf/printf 輕巧, 高效, 但不是類型安全的, 沒有擴展性; 需要把讀寫的變量和控制讀寫格式的信息分開(FORTRAN style);
>>和<<, 實現重載函數可以處理不同的類型; 讀寫語法形式相同, 不需要記住格式規定;
12345678910111213141516 int i;Rational r; //有理數cin >> i >> r;cout << i << r;class Rational {public: Rational(int numerator = 0, int denominator = 1);...private: int n, d; // 分子,分母 friend ostream& operator<<(ostream& s, const Rational& r);};ostream& operator<<(ostream& s, const Rational& r){ s << r.n << '/' << r.d; return s;}
>"opertaor<<"不是成員函數(是操作符);
相對不足:
1) 有些iostream的操作比起相應的C stream效率低;
2) 標准化過程中, iostream庫在底層做了很多修改, 對要求最大可移植性的程序來說, 不同的廠商遵循標准的程度不同;
3) iostream庫的類有構造函數, <stdio.h>裡的函數沒有, 在某些涉及靜態對象初始化順序的時候, 如果可以確定沒有隱患, 用標准C庫更簡單實用;
優點: iostream庫的類和函數類型安全, 可擴展性好;
庫的包含: <iostream>
#include <iostream.h> 得到的是置於全局空間的iostream庫元素;
#include <iostream> 得到的是置於名字空間std下的iostream庫元素;
全局空間獲取元素可能導致名字沖突;