1,類型名的第一個字母大寫,最後以_T結尾
2,變量和函數名首字母小寫,其後每一個單詞的首字母大寫,其它小寫。
3,全大寫的函數名,和小寫的函數名一樣,不過是增加了錯誤處理而已,編譯時用inline實現。
4,指針用p開頭或者用Ptr結尾。
5,用前綴區分作用域:i_ (instance scope)、c_ (class scope)、g_ (global scope)、f_ (file scope)。yathing:不加下劃線,表示數據類型,m_ 表示成員變量,等等......
6,全大寫的前綴,表示項目名、Packet或者Library等(命名空間級別以上)。
7,用可發音的名字。
8,詞彙通用、通俗、但是避免誤解。
9,lhs,函數左值參數;rhs,函數右值參數。
10,a、an、any區分重名參數。
11,指針和引用的區別關鍵:NULL是不是合法值。
12,無符號、位操作,慎用。效率低下、兼容性問題等。
13,內置數據類型傳值、非內置類型傳引用(首選)或指針。
14,若不得不使用參數不確定的函數,用<stdarg.h>提供的方法[1]。
15,若必須返回值,不要強行返回引用[2]。
16,禁止成員函數返回成員的引用或指針,只讀的例外[3]。
17,顯示禁止編譯器自動生成不需要的函數[4]。
18,絕不要重新定義繼承來的非虛函數。
19,絕不要重新定義缺省參數值。
20,多重繼承的基類析構函數都應該是虛函數。
21,純虛函數:只繼承接口並且派生類必須提供實現。一般虛函數:繼承接口並提供缺省實現。
22,類型差異不影響行爲時,用模板,否則用繼承。
23,誰申請誰釋放[5]。
24,關於虛友元函數[6]。
25,關於虛構造函數[7]。
26,不要用構造函數初始化靜態成員。
27,包含資源管理的類應自定義拷貝、賦值、析構函數。
28,拷貝構造、賦值、析構函數要麼全自定義,要麼全生成。
29,循環隊列的問題常出現在:插入元素使得下標從MAX-1繞回0,刪除元素使得下標從0繞回到MAX-1,插入頭一兩個元素,以及刪除最後一兩個元素時。如果我們將隊首設在MAX-3處,可以將這些情況全覆蓋住。
30,任何變量和成員函數,首選const修飾。
31,確保自定義操作符能和其它操作符混合使用[8]。
32,顯式轉換而不是隱式
33,自定義類提供asInt()這樣的顯式轉換而不是隱式轉換函數int operator int(void)
34,用關鍵字explicit防止單參數構造函數的類型轉換功能[9]。
35,模板的使用如果有限制條件,一定要在註釋和文檔中描述清楚。
36,嵌套template的>>中間要加空格以區別operator >>
37,在循環過程中不要修改循環計數器。
38,不能用goto跳出、跳入循環體,不能用goto跳出、跳入程序塊。
39,用inline代替宏函數、用typedef代替類型定義、用const常數代替宏常數
40,每一行不超過78個字符
41,case若不需要break則一定要加註釋聲明
42,註釋完善代碼,而不是重複代碼(最簡單的:這麼做是爲了什麼)
43,用#if 0而不是/**/註釋掉大段的代碼
44,註釋不能超出被註釋代碼所包含的內容[10],這個毛病初學者常犯——把註釋當文檔用了。
45,註釋中避免引用容易變化的信息
46,註釋下限:每5行代碼至少一行註釋;沒聽說過有上限。
47,該用volatile時一定要用[11]。
ps:本書後面還有附錄代碼,以示例的形式展現各條編程規範。因爲時間緣故,就不作整理了吧!^_^
[1] <stdarg.h>中定義的宏提供了一種安全有效的訪問參數鏈的方法。
[2] 相應的例子,參見《返回值和返回引用》
[3] 和Jal商量了一會兒,我們的意見是:指針的效率慢,所以儘量用引用(能夠用的場合實在不算太多,類裏面返回引用,最好還要加const)。但是引用實在是很容易令人犯錯,算是仁者見仁、智者見智吧!
[4] 比如,聲明拷貝構造函數、賦值函數,防止友元使用或者定義。
[5] 利用引用計數,每次拷貝或賦值的時候都只是將引用數加1,而在每個引用計數對象析構的時候引用計數減1,只有當引用計數爲0時才調用析構函數。計算機中使用引用計數的應用很多,如:多用戶打開同一個文件、內存頁面的引用等。
[6] C++語法不允許(非成員的)友元函數爲虛函數,不過我們可以通過編程技巧達到虛友元想達到的效果。
- /************************************************************************/
- /* 一般情況下基類和派生類都要加入友元operator<<打印輸出,
- 我們這裏卻採用虛函數print輸出(相當於完成友元功能的虛函數) */
- /************************************************************************/
- class Base_T
- {
- public:
- virtual void print(ostream&){}
- };
- class Derived :public Base_T
- {
- public:
- virtual void print(ostream&){}
- };
- //它不是任何類的友元,只需要帶基類引用作爲第二個參數即可。
- ostream& operator<<(ostream& output,Base_T& anObject)
- {
- anObject.print();
- }
[7] C++語法不允許構造函數爲虛函數,但有時又需要這樣的函數:它們能夠根據不同情況構造出不同的派生類,這類函數實際起到虛構造函數的作用。參見下面的代碼:
- class Base_T
- {
- public:
- //根據自身this類型,克隆出一個新對象
- virtual Base_T& clone(void);
- };
- Base_T& baseRef = aDrivedObj;
- Base_T& anotherBaseRef = aDerivedObj.clone();
[8] operator ^()被重定義後,x^y+b會被解釋爲x^(y+b),而不是所希望的(x^y)+b,因爲編譯器是按異或的優先級確定運算順序的。
[9] 單參數構造函數的一個隱含意思是:將該參數轉換成該類的一個對象。explicit則用來禁止編譯器隱式調用該構造函數,以防止隱式的類型轉換。
[10]
- 沒必要說二叉樹,此處代碼不包括實現細節。
- //Search the set for the item using a binary-tree search algorithm
- bool contains(Item anItem);
- 恰當
- //Return true if the specified item is contained in the root
- bool contains(Item anItem);
[11] 關鍵字volatile的含義是:其所修飾的變量的值可能會發生變化(比如中斷程序修改該變量),而這種變化是編譯器察覺不到的。例子:
- char c = ioRegisters.input;//應該用volatile修飾ioRegisters.input
- c=ioRegisters.input;//否則編譯器優化時可能刪掉此句