編碼原則實例------c++程序設計原理與實踐(進階篇)
編碼原則:
- 一般原則
- 預處理原則
- 命名和布局原則
- 類原則
- 函數和表達式原則
- 硬實時原則
- 關鍵系統原則
(硬實時原則、關鍵系統原則僅用於硬實時和關鍵系統程序設計)
(嚴格原則都用一個大寫字母R及其編號標識,而推薦原則都用小寫字母r及其編號標識,對於前者程序員必須嚴格遵守,而後者則偶爾可以不遵守)
1、一般原則
R100:任何函數和類的代碼規模都不應超過200行(不包括註釋)。
原因:長的函數和類會更復雜,因而難以理解和測試。
r101:任何函數和類都應該能完全顯示在一屏上,並完成單一的邏輯功能。
原因:如果程序員只能看到函數或類的一部分,就很可能漏掉錯誤的部分。如果一個函數試圖完成多個功能,與單功能的函數相比,其規模就可能很大,而且會更復雜。
R102:所以代碼都應該遵守ISO/IEC 14882:2011(E)C++標準。
原因:在ISO/IEC 14882標準之上的擴展金額變形可能會不穩定,定義不明確,而且可能影響移植性。
2、預處理原則
R200:除了用於源碼控制的#ifdef和#ifndef之外,不要使用宏。
原因:宏不遵守定義域和類型規則,而且使代碼變得更不清晰、不易讀。
R201:#include 只能用於包含頭文件(*.h)。
原因:#include 用於訪問接口的聲明而非實現細節。
R202:所以的#incldue語句都應位於任何非預處理聲明之前。
原因:如果#include語句位於程序中間,就很可能被閱讀程序的人忽略,而且容易導致程序不同部分對名字的解析不一致。
R203:頭文件(*.h)不應包含非常量變量的定義或非內聯、非模板函數定義。
原因:頭文件應該包含接口聲明而非實現細節。但是,常量常被看作接口的一部分;出於性能的考慮,一些非常簡單的函數應該作為內聯函數(因此應該放在頭文件中);而當前的編譯器要求完整的模板定義都放在頭文件中。
3、命名和布局原則
R300:應該使用縮進,並且在一個源碼文件中縮進風格應該一致。
原因:可讀性和代碼風格。
R301:每條新語句都另起一行。
原因:可讀性。
例子:
int a=7;x=a+7;f(x,9); //違反
int a=7; x=a+7; f(x,9); //正確
例子:
if(p<q)cout<<*p; //違反 if(p<q) cout<<*p; //正確
R302:標識符的名字應該都具有描述性。
標識符可以包含常見的縮寫和字頭縮略。
如果x、y、i、j是按習慣方式使用,可以認為是有描述性的。
使用下劃線風格(number_of_elements)而不是字頭縮略風格(numberOfElement)。
不要使用匈牙利命名法。
類型、模板和命名空間的命名都以大寫字母開頭。
避免過長的名字。
例子:Device_driver 和Buffer_poor。
原因:可讀性。
註意:c++標準規定,以下劃線開頭的標識符留作語言實現所用,因此在用戶程序中應被禁止。
例外:調用經過認證的庫,來自庫中名字是可以使用的。
R303:標識符不能只在以下方面不同:
- 大小寫不同;
- 只相差下劃線;
- 只是字母O、數字0或字母D間的替換;
- 只是字母I、數字1後字母l之間的替換;
- 只是字母S和數字5之間的替換;
- 只是字面Z和字數2之間的替換;
- 只是字母與n和字母h直接的替換。
例子:Head和head //違反
原因:可讀性。
R304:標識符不能只包含大寫字母和下劃線。
例子:BLUE和BLUE_CHEESE //違反
原因:全部大寫字母的標識符被廣泛用於宏名,可能用於經過認證的庫中的#include文件,而不應該用於客戶程序。
例外:宏名用於保護#include不被重復包含。
4、函數和表達式原則
r400:內層循環的標識符和外層循環的標識符不應重名。
原因:可讀性和代碼風格。
例子:
int var=9;{int var=7;++var} //違反:var重名
R401:聲明的作用域應該盡量小。
原因:保持變量的初始化和使用盡量靠近,以降低混亂的可能性;令離開作用域的變量釋放其資源。
R402:所以變量都要初始化。
例子:
int var; //違反:var沒有初始化
原因:未初始化的變量通常是錯誤之源。
例外:如果數組或容器會立即從輸入接受數據,則不必初始化。
註意:許多類型,例如vector和string,有默認的構造函數來完成初始化。
R403:不應使用類型轉換。
原因:類型轉換是錯誤之源。
例外:dynamic_cast可以使用。
例外:新風格的類型轉換可以使用,用來將硬件地址轉換為指針,或者將從程序外部(如GUI庫)獲取的void*轉換為恰當類型的指針。
R404:函數接口中不應使用內置數組類型,即,如果一個函數參數是指針,那麽它必須指向單個元素。如果希望傳遞數組,應使用Array_ref。
原因:數組只能以指針方式傳遞,而元素數目無法附著其上,只能分開傳遞。而且,隱式的數組到指針的轉換和派生類到基類的轉換會引起內存錯誤。
5、類原則
R500:對於沒有共有數據成員的類,用class聲明。對沒有私有數據成員的類,用struct聲明。不要定義既有共有數據成員,又有私有數據成員的類。
原因:清晰性。
r501:如果類包含析構函數或者指針/引用類型的成員,必須為其定義恰當的或禁止(即,不能使用默認版本)拷貝構造函數和拷貝賦值運算符。
原因:析構函數通常會釋放資源。對於具有析構函數或者指針和引用類型的類,默認拷貝語義幾乎不可能”做正確的事“。
R502:如果類包含虛函數,那麽它必須具有虛析構函數。
原因:虛函數可以通過基類接口使用,通過基類接口訪問對象的函數可能會刪除對象,派生類必須有某種機制(析構函數)來進行清理工作。
R503:接受單一參數的構造函數必須顯式聲明。
原因:避免奇怪的隱式類型轉換。
6、硬實時原則
R800:不應使用異常。
原因:異常不可預測。
R801:new只能在初始化時使用。
原因:不可預測。
例外:可以用定址的new從棧中分配內存。
R802:不應使用delete。
原因:不可預測,可能會引起碎片。
R803:不應使用dynamic_cast。
原因:不可預測(假定使用普通方法實現的)。
R804:不應使用標準庫容器,std::array除外
原因:不可預測(假定是用普通方法實現的)。
7、關鍵系統原則
R900:遞增和遞減運算不能作為子表達式。
例子:
int x=v[++i]; //違反
++i;
int x=v[i]; //正確
原因:可能會被漏掉。
R901:代碼不應依賴於算法表達式優先級之下的優先級規則。
例子:
x=a*b+c; //正確
例子:
if(a<b||c<=d) //違反:應加上括號(a<b)和(c<=d)
原因:c/c++基礎較差的程序員寫出的代碼中常常會有優先級混亂的情況。
c++程序設計原理與實踐(進階篇)
編碼原則實例------c++程序設計原理與實踐(進階篇)