1. 程式人生 > >編碼原則實例------c++程序設計原理與實踐(進階篇)

編碼原則實例------c++程序設計原理與實踐(進階篇)

組類型 運算 奇怪 head 不能 gui 簡單的 版本 布局

編碼原則:

  • 一般原則
  • 預處理原則
  • 命名和布局原則
  • 類原則
  • 函數和表達式原則
  • 硬實時原則
  • 關鍵系統原則

(硬實時原則、關鍵系統原則僅用於硬實時和關鍵系統程序設計)

(嚴格原則都用一個大寫字母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++程序設計原理與實踐(進階篇)