C++命名規範

對於不一樣的編程語言來講,具體的編碼規範能夠有很大的不一樣,可是其宗旨都是一致的,就是保證代碼在高質量完成需求的同時具有良好的可讀性、可維護性。例如咱們能夠規定某個項目的C語言程序要遵循這樣的規定:變量的命名,頭文件的書寫和#include 等等。html

下面是一些廣爲採用的編碼規範:java

  • GNU Coding Standards
  • Guidelines for the Use of the C Language in Vehicle Based Software
  • C++ Coding Guidelines
  • SUN Code Conventions for Java

如下是一些介紹編碼、編碼規範的書籍:程序員

  • C++編碼規範,陳世忠,人民郵電出版社,2002
  • 高質量程序設計指南:C++/C語言,林銳等,電子工業出版社,2003

注:如下只是根據課題組已有的經驗給出的總結,並不是對全部場景均適用。編程

對於高質量的工程,通常會作到:數組

  1. 代碼簡潔精煉,美觀,可讀性好,高效率,高複用,可移植性好,高內聚,低耦合,沒有冗餘,不符合這些原則,必須特別說明。
  2. 規範性,代碼有規可循。特殊排版、特殊語法、特殊指令,必須特別說明。

 

1、文件排版方面

  1. 包含頭文件
    1.1 先系統頭文件,後用戶頭文件。
    1.2 系統頭文件,穩定的目錄結構,應採用包含子路徑方式。
    1.3 自定義頭文件,不穩定目錄結構,應在dsp中指定包含路徑。
    1.4 系統頭文件應用:#include <xxx.h>
    1.5 自定義同文件應用:#include "xxx.h"
    1.6 只引用須要的頭文件。
  2. h和cpp文件
    2.1 頭文件命名爲*.h,內聯文件命名爲*.inl;C++文件命名爲*.cpp
    2.2 文件名用大小寫混合,或者小寫混合。例如DiyMainView.cppinfoview.cpp。不要用無心義的名稱:例如XImage.cppSView.cppxlog.cpp
    2.3 頭文件除了特殊狀況,應使用#ifdef控制塊。
    2.4 頭文件#endif應採用行尾註釋。
    2.5 頭文件,首先是包含代碼塊,其次是宏定義代碼塊,而後是全局變量,全局常量,類型定義,類定義,內聯部分。
    2.6 CPP文件,包含指令,宏定義,全局變量,函數定義。
  3. 文件結構
    3.1 文件應包含文件頭註釋和內容。
    3.2 函數體類體之間原則上用2個空行,特殊狀況下可用一個或者不須要空行。
  4. 空行
    4.1 文件頭、控制塊,#include部分、宏定義部分、class部分、全局常量部分、全局變量部分、函數和函數之間,用兩個空行。

 

2、註釋方面

  1. 文件頭註釋
    1.1 做者,文件名稱,文件說明,生成日期(可選)
  2. 函數註釋
    2.1 關鍵函數必須寫上註釋,說明函數的用途。
    2.2 特別函數參數,須要說明參數的目的,由誰負責釋放等等。
    2.3 除了特別狀況,註釋寫在代碼以前,不要放到代碼行以後。
    2.4 對每一個#else#endif給出行末註釋。
    2.5 關鍵代碼註釋,包括但不限於:賦值,函數調用,表達式,分支等等。
    2.6 善未實現完整的代碼,或者須要進一步優化的代碼,應加上 // TODO ...
    2.7 調試的代碼,加上註釋 // only for DEBUG
    2.8 須要引發關注的代碼,加上註釋 // NOTE ...
    2.9 對於較大的代碼塊結尾,如for,while,do等,可加上 // end for|while|do

 

3、命名方面

  1. 原則
    1.1 同一性:在編寫一個子模塊或派生類的時候,要遵循其基類或總體模塊的命名風格,保持命名風格在整個模塊中的同一性。
    1.2 標識符組成:標識符采用英文單詞或其組合,應當直觀且能夠拼讀,可望文知意,用詞應當準確,避免用拼音命名。
    1.3 最小化長度 && 最大化信息量原則:在保持一個標識符意思明確的同時,應當儘可能縮短其長度。
    1.4 避免過於類似:不要出現僅靠大小寫區分的類似的標識符,例如"i""I""function""Function"等等。
    1.5 避免在不一樣級別的做用域中重名:程序中不要出現名字徹底相同的局部變量和全局變量,儘管二者的做用域不一樣而不會發生語法錯誤,但容易令人誤解。
    1.6 正確命名具備互斥意義的標識符:用正確的反義詞組命名具備互斥意義的標識符,如:"nMinValue" 和 "nMaxValue""GetName()" 和"SetName()" ….
    1.7 避免名字中出現數字編號:儘可能避免名字中出現數字編號,如Value1,Value2等,除非邏輯上的確須要編號。這是爲了防止程序員偷懶,不願爲命名動腦筋而致使產生無心義的名字(由於用數字編號最省事)。
  2. T,C,M,R類
    2.1 T類表示簡單數據類型,不對資源擁有控制權,在析構過程當中沒有釋放資源動做。
    2.2 C表示從CBase繼承的類。該類不能從棧上定義變量,只能從堆上建立。
    2.3 M表示接口類。
    2.4 R是資源類,一般是系統固有類型。除了特殊狀況,不該在開發代碼中出現R類型。
  3. 函數名
    3.1 M類的函數名稱應採用HandleXXX命名,例如:HandleTimerEvent;不推薦採用java風格,例如 handleTimerEvent;除了標準c風格代碼,不推薦用下劃線,例如,handle_event
    3.2 Leave函數,用後綴L。
    3.3 Leave函數,且進清除棧,用後綴LC。
    3.4 Leave函數,且刪除對象,用後綴LD。
  4. 函數參數
    4.1 函數參數用a做爲前綴。
    4.2 避免出現和匈牙利混合的命名規則如apBuffer名稱。用aBuffer便可。
    4.3 函數參數比較多時,應考慮用結構代替。
    4.4 若是不能避免函數參數比較多,應在排版上可考慮每一個參數佔用一行,參數名豎向對齊。
  5. 成員變量
    5.1 成員變量用m最爲前綴。
    5.2 避免出現和匈牙利混合的命名規則如mpBuffer名稱。用mBuffer便可。
  6. 局部變量
    6.1 循環變量和簡單變量採用簡單小寫字符串便可。例如,int i;
    6.2 指針變量用p打頭,例如void* pBuffer;
  7. 全局變量
    7.1 全局變量用g_最爲前綴。
  8. 類名
    8.1 類和對象名應是名詞。
    8.2 實現行爲的類成員函數名應是動詞。
    8.3 類的存取和查詢成員函數名應是名詞或形容詞。
  9. 風格兼容性
    9.1 對於移植的或者開源的代碼,能夠沿用原有風格,不用C++的命名規範。

 

4、代碼風格方面

  1. Tab和空格
    1.1 每一行開始處的縮進只能用Tab,不能用空格,輸入內容以後統一用空格。除了最開始的縮進控制用Tab,其餘部分爲了對齊,須要使用空格進行縮進。這樣能夠避免在不一樣的編輯器下顯示不對齊的狀況。
    1.2 在代碼行的結尾部分不能出現多餘的空格。
    1.3 不要在"::","->","."先後加空格。
    1.4 不要在",",";"以前加空格。
  2. 類型定義和{
    2.1 類,結構,枚舉,聯合:大括號另起一行
  3. 函數
    3.1 函數體的{須要新起一行,在{以前不能有縮進。
    3.2 除了特別狀況,函數體內不能出現兩個空行。
    3.3 除了特別狀況,函數體內不能宏定義指令。
    3.4 在一個函數體內,邏揖上密切相關的語句之間不加空行,其它地方應加空行分隔。
    3.5 在頭文件定義的inline函數,函數之間能夠不用空行,推薦用一個空行。
  4. 代碼塊
    4.1 "if"、"for"、"while"、"do"、"try"、"catch" 等語句自佔一行,執行語句不得緊跟其後。不論執行語句有多少都要加 "{ }" 。這樣能夠防止書寫和修改代碼時出現失誤。
    4.2 "if"、"for"、"while"、"do"、"try"、"catch" 的括號和表達式,括號可緊挨關鍵字,這樣強調的是表達式。
  5. else
    5.1 if語句若是有else語句,用 } else { 編寫爲一行,不推薦用 3 行代碼的方式。
  6. 代碼行
    6.1 一行代碼只作一件事情,如只定義一個變量,或只寫一條語句。這樣的代碼容易閱讀,而且方便於寫註釋。
    6.2 多行變量定義,爲了追求代碼排版美觀,可將變量豎向對齊。
    6.3 代碼行最大長度宜控制在必定個字符之內,能在當前屏幕內所有可見爲宜。
  7. switch語句
    7.1 case關鍵字應和switch對齊。
    7.2 case子語句若是有變量,應用{}包含起來。
    7.3 若是有並列的相似的簡單case語句,可考慮將case代碼塊寫爲一行代碼。
    7.4 簡單的case之間可不用空行,複雜的case之間應考慮用空行分割開。
    7.5 case字語句的大括號另起一行,不要和case寫到一行。
    7.6 爲全部switch語句提供default分支。
    7.7 若某個case不須要break必定要加註釋聲明。
  8. 循環
    8.1 空循環可用 for( ;; ) 或者 while( 1 ) 或者 while( true )

  9. 9.1 類繼承應採用每一個基類佔據一行的方式。
    9.2 單繼承可將基類放在類定義的同一行。若是用多行,則應用Tab縮進。
    9.3 多繼承在基類比較多的狀況下,應將基類分行,並採用Tab縮進對齊。
    9.4 重載基類虛函數,應在該組虛函數前寫註釋 // implement XXX
    9.5 友元聲明放到類的末尾。

  10. 10.1 不要用分號結束宏定義。
    10.2 函數宏的每一個參數都要括起來。
    10.3 不帶參數的宏函數也要定義成函數形式。
  11. goto
    11.1 儘可能不要用goto。

 

5、類型

  1. 定義指針和引用時*&緊跟類型。
  2. 儘可能避免使用浮點數,除非必須。
  3. typedef簡化程序中的複雜語法。
  4. 避免定義無名稱的類型。例如:typedef enum { EIdle, EActive } TState;
  5. 少用union,若是必定要用,則採用簡單數據類型成員。
  6. enum取代(一組相關的)常量。
  7. 不要使用魔鬼數字。
  8. 儘可能用引用取代指針。
  9. 定義變量完成後當即初始化,勿等到使用時才進行。
  10. 若是有更優雅的解決方案,不要使用強制類型轉換。

 

6、表達式

  1. 避免在表達式中用賦值語句。
  2. 避免對浮點類型作等於或不等於判斷。
  3. 不能將枚舉類型進行運算後再賦給枚舉變量。
  4. 在循環過程當中不要修改循環計數器。
  5. 檢測空指針,用 if( p )
  6. 檢測非空指針,用 if( ! p )

 

7、函數

  1. 引用
    1.1 引用類型做爲返回值:函數必須返回一個存在的對象。
    1.2 引用類型做爲參數:調用者必須傳遞一個存在的對象。
  2. 常量成員函數
    2.1 表示該函數只讀取對象的內容,不會對對象進行修改。
  3. 返回值
    3.1 除開void函數,構造函數,析構函數,其它函數必需要有返回值。
    3.2 當函數返回引用或指針時,用文字描述其有效期。
  4. 內聯函數
    4.1 內聯函數應將函數體放到類體外。
    4.2 只有簡單的函數纔有必要設計爲內聯函數,複雜業務邏輯的函數不要這麼作。
    4.3 虛函數不要設計爲內聯函數。
  5. 函數參數
    5.1 只讀取該參數的內容,不對其內容作修改,用常量引用。
    5.2 修改參數內容,或須要經過參數返回,用很是量應用。
    5.3 簡單數據類型用傳值方式。
    5.4 複雜數據類型用引用或指針方式。

 

8、類

  1. 構造函數
    1.1 構造函數的初始化列表,應和類的順序一致。
    1.2 初始化列表中的每一個項,應獨佔一行。
    1.3 避免出現用一個成員初始化另外一個成員。
    1.4 構造函數應初始化全部成員,尤爲是指針。
    1.5 不要在構造函數和析構函數中拋出異常。
  2. 純虛函數
    2.1 M類的虛函數應設計爲純虛函數。
  3. 構造和析構函數
    3.1 若是類能夠繼承,則應將類析構函數設計爲虛函數。
    3.2 若是類不容許繼承,則應將類析構函數設計爲非虛函數。
    3.3 若是類不能被複制,則應將拷貝構造函數和賦值運算符設計爲私有的。
    3.4 若是爲類設計了構造函數,則應有析構函數。
  4. 成員變量
    4.1 儘可能避免使用mutableVolatile
    4.2 儘可能避免使用公有成員變量。
  5. 成員函數
    5.1 努力使類的接口少而完備。
    5.2 儘可能使用常成員函數代替很是成員函數,const函數
    5.3 除非特別理由,毫不要從新定義(繼承來的)非虛函數。(這樣是覆蓋,基類的某些屬性無初始化)
  6. 繼承
    6.1 繼承必須知足IS-A的關係,HAS-A應採用包含。
    6.2 虛函數不要採用默認參數。
    6.3 除非特別須要,應避免設計大而全的虛函數,虛函數功能要單一。
    6.4 除非特別須要,避免將基類強制轉換成派生類。
  7. 友元
    7.1 儘可能避免使用友元函數和友元類。

 

9、錯誤處理

  1. 申請內存用new操做符。
  2. 釋放內存用delete操做符。
  3. newdeletenew[]delete[]成對使用。
  4. 申請內存完成以後,要檢測指針是否申請成功,處理申請失敗的狀況。
  5. 誰申請誰釋放。優先級:函數層面,類層面,模塊層面。
  6. 釋放內存完成後將指針賦空,避免出現野指針。
  7. 使用指針前進行判斷合法性,應考慮到爲空的狀況的處理。
  8. 使用數組時,應先判斷索引的有效性,處理無效的索引的狀況。
  9. 代碼不能出現編譯警告。
  10. 使用錯誤傳遞的錯誤處理思想。
  11. 衛句風格:先處理全部可能發生錯誤的狀況,再處理正常狀況。
  12. 嵌套do-while(0)宏:目的是將一組語句變成一個語句,避免被其餘if等中斷。

 

10、性能

  1. 使用前向聲明代替#include指令。Class M;
  2. 儘可能用++i代替i++。即用前綴代替後綴運算。
  3. 儘可能在for循環以前,先寫計算估值表達式。
  4. 儘可能避免在循環體內部定義對象。
  5. 避免對象拷貝,尤爲是代價很高的對象拷貝。
  6. 避免生成臨時對象,尤爲是大的臨時對象。
  7. 注意大尺寸對象數組。
  8. 80-20原則。

 

11、兼容性

  1. 遵照ANSI C和ISO C++國際標準。
  2. 確保類型轉換不會丟失信息。
  3. 注意雙字節字符的兼容性。
  4. 注意運算溢出問題。
  5. 不要假設類型的存儲尺寸。
  6. 不要假設表達式的運算順序。
  7. 不要假設函數參數的計算順序。
  8. 不要假設不一樣源文件中靜態或全局變量的初始化順序。
  9. 不要依賴編譯器基於實現、未明確或未定義的功能。
  10. 將全部#include的文件名視爲大小寫敏感。
  11. 避免使用全局變量、靜態變量、函數靜態變量、類靜態變量。在使用靜態庫,動態庫,多線程環境時,會致使兼容性問題。
  12. 不要從新實現標準庫函數,如STL已經存在的。

注:本文做者liyuefeilong的專欄,原文連接地址我的總結的一些C/C++編碼規範 - CSDN博客,如需轉載請聯繫得到受權。作一隻勤勞的IT乾貨搬運工,只爲成就更好的你!多線程

相關文章
相關標籤/搜索