首先,強烈推薦林銳博士這本《高質量C++/C 編程指南》,請花一兩個小時認真閱讀這本百頁經書,你將會獲益匪淺。草草看過,個人收獲記錄如下。
頭文件的作用略作解釋:
(1)通過頭文件來調用庫功能。在很多場合,源代碼不便(或不准)向用戶公布,只要向用戶提供頭文件和二進制的庫即可。用戶只需要按照頭文件中的接口聲明來調用庫功能,而不必關心接口怎麼實現的。編譯器會從庫中提取相應的代碼。
(2)頭文件能加強類型安全檢查。如果某個接口被實現或被使用時,其方式與頭文件中的聲明不一致,編譯器就會指出錯誤,這一簡單的規則能大大減輕程序員調試、改錯的負擔。
另:extern可以置於變量或者函數前,以標示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。如果函數的聲明中帶有關鍵字extern,僅僅是暗示這個函數可能在別的源文件裡定義,沒有其它作用。
空行
a.在每個類聲明之後、每個函數定義結束之後都要加空行。
b.在一個函數體內,邏揖上密切相關的語句之間不加空行,其它地方應加空行分隔。(這一條值得注意)
代碼行
a.一行代碼只做一件事情,如只定義一個變量,或只寫一條語句。這樣的代碼容易閱讀,並且方便於寫注釋。
b.if、for、while、do 等語句自占一行,執行語句不得緊跟其後。不論執行語句有多少都要加{}。這樣可以防止書寫失誤。
other();
c.盡可能在定義變量的同時初始化該變量(就近原則)
代碼行內的空格
a.關鍵字後要留空格,如const、virtual、inline、case以及if、for、while;函數名之後不要留空格,緊跟左括號‘(’,以與關鍵字區別。
b.逗號與分號之後要留空格;“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前後應當加空格;一元操作符前後不加空格。
c.象“[]”、“.”、“->”這類操作符前後不加空格。
d.對於表達式比較長的for 語句和if 語句,為了緊湊起見可以適當地去掉一些空格。
(i=; i<; i++)
長行拆分
代碼行最大長度宜控制在70 至80 個字符以內。長表達式要在低優先級操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進行適當的縮進,使排版整齊,語句可讀。
((very_longer_variable1 >=&& (very_longer_variable3 <=&& (very_longer_variable5 <=
注釋
a.注釋是對代碼的“提示”,而不是文檔。程序中的注釋不可喧賓奪主,注釋太多了會讓人眼花缭亂。注釋的花樣要少。
b.邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。
c.盡量避免在注釋中使用縮寫,特別是不常用縮寫。
d.注釋的位置應與被描述的代碼相鄰,可以放在代碼的上方或右方,不可放在下方。
f.當代碼比較長,特別是有多重嵌套時,應當在一些段落的結束處加注釋,便於閱讀。
類的版式
類的版式主要有兩種方式:
(1)將private 類型的數據寫在前面,而將public 類型的函數寫在後面。采用這種版式的程序員主張類的設計“以數據為中心”,重點關注類的內部結構。
(2)將public 類型的函數寫在前面,而將private 類型的數據寫在後面。采用這種版式的程序員主張類的設計“以行為為中心”,重點關注的是類應該提供什麼樣的接口(或服務)。
建議讀者采用“以行為為中心”的書寫方式,即首先考慮類應該提供什麼樣的函數。
Func1( Func2(
共性規則
a.標識符應當直觀且可以拼讀,可望文知意;標識符的長度應當符合“min-length && max-information”原則。
b.命名規則盡量與所采用的操作系統或開發工具的風格保持一致。
例如 Windows 應用程序的標識符通常采用“大小寫”混排的方式,如AddChild。而Unix 應用程序的標識符通常采用“小寫加下劃線”的方式,如add_child。別把這兩類風格混在一起使用。
c.變量的名字應當使用“名詞”或者“形容詞+名詞”;全局函數的名字應當使用“動詞”或者“動詞+名詞”(動賓詞組)。
d.盡量避免名字中出現數字編號,如Value1,Value2 等,除非邏輯上的確需要編號。這是為了防止程序員偷懶,不肯為命名動腦筋而導致產生無意義的名字(因為用數字編號最省事)。
簡單的Windows 應用程序命名規則
a.類名和函數名用大寫字母開頭的單詞組合而成
b.變量和參數用小寫字母開頭的單詞組合而成。
c.常量全用大寫的字母,用下劃線分割單詞。
d.靜態變量加前綴s_(表示static)。
e.如果不得已需要全局變量,則使全局變量加前綴g_(表示global)。
f.類的數據成員加前綴m_(表示member),這樣可以避免數據成員與成員函數的參數同名。
g.為了防止某一軟件庫中的一些標識符和其它軟件庫中的沖突,可以為各種標識符加上能反映軟件性質的前綴。
if語句
不可將浮點變量用“==”或“!=”與任何數字比較。
((x >= -EPSINON) && (x <=
有時候我們可能會看到 if (NULL == p) 這樣古怪的格式。不是程序寫錯了,是程序員為了防止將 if (p == NULL) 誤寫成 if (p = NULL),而有意把p 和NULL 顛倒。編譯器認為 if (p = NULL) 是合法的,但是會指出 if (NULL = p)是錯誤的,因為NULL不能被賦值。
程序中有時會遇到 if/else/return 的組合,應該將如下不良風格的程序
y;改寫為
(condition ? x : y);
循環語句的效率
C++/C 循環語句中,for 語句使用頻率最高,while 語句其次,do 語句很少用。提高循環體效率的基本辦法是降低循環體的復雜性。
在多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放在最外層,以減少CPU 跨切循環層的次數。
switch 語句
不要忘記最後那個default 分支。即使程序真的不需要default 處理,也應該保留語句 default : break; 這樣做並非多此一舉,而是為了防止別人誤以為你忘了default 處理。
goto 語句
我們主張少用、慎用goto 語句,而不是禁用。
const 與 #define 的比較
C++ 語言可以用const 來定義常量,也可以用 #define 來定義常量。但是前者比後者有更多的優點:
(1)const 常量有數據類型,而宏常量沒有數據類型。編譯器可以對前者進行類型安全檢查。而對後者只進行字符替換,沒有類型安全檢查,並且在字符替換可能會產生意料不到的錯誤(邊際效應)。
(2)有些集成化的調試工具可以對const 常量進行調試,但是不能對宏常量進行調試。
建議:在C++ 程序中只使用const 常量而不使用宏常量。
類中的常量
有時我們希望某些常量只在類中有效。由於#define 定義的宏常量是全局的,不能達到目的,於是想當然地覺得應該用const 修飾數據成員來實現。const 數據成員的確是存在的,但其含義卻不是我們所期望的。const 數據成員只在某個對象生存期內是常量,而對於整個類而言卻是可變的,因為類可以創建多個對象,不同的對象其const 數據成員的值可以不同。不能在類聲明中初始化const 數據成員。以下用法是錯誤的,因為類的對象未被創建時,編譯器不知道SIZE 的值是什麼。
SIZE = ; array[SIZE]; };
const 數據成員的初始化只能在類構造函數的初始化表中進行,例如
size); size) : SIZE(size) ); A b();
怎樣才能建立在整個類中都恆定的常量呢?別指望const 數據成員了,應該用類中的枚舉常量來實現。例如
{ SIZE1 = , SIZE2 = };
枚舉常量不會占用對象的存儲空間,它們在編譯時被全部求值。枚舉常量的缺點是:它的隱含數據類型是整數,其最大值有限,且不能表示浮點數(如PI=3.14159)。