英文版:http://google-styleguide.googlecode.com/svn/trunk/cppguide.xmlhtml
中文版:http://zh-google-styleguide.readthedocs.org/en/latest/google-cpp-styleguide/c++
google c++ 編碼規範:http://blog.csdn.net/xiexievv/article/details/50972809程序員
網上有電子版 PDF ,能夠下載看下。。。(電子版下載地址:https://pan.baidu.com/s/1i3gc7lF)算法
Google C++ 編碼規範很早就已經公開了,李開復也在其微博上公開分享:」我認爲這是地球上最好的一份C++編程規範,沒有之一,建議廣大國內外IT研究使用。「編程
Google C++ Style Guide是一份不錯的C++編碼指南,下面是一張比較全面的說明圖,能夠在短期內快速掌握規範的重點內容。不過規範畢竟是人定的,記得活學活用。多線程
一些條目每每有例外,好比下面這些,因此本圖不能代替文檔,有時間仍是把PDF認真閱讀一遍吧。框架
異常在測試框架中確實很好用ide
RTTI在某些單元測試中很是有用svn
在記錄日誌時可使用流
操做符重載 不提倡使用,有些STL 算法確實須要重載operator==時能夠這麼作。函數
注:原圖較大,在新標籤頁中打開或保存到本地打開更清晰
頭文件
函數參數順序
C/C++函數參數分爲輸入參數和輸出參數兩種,有時輸入參數也會輸出(注:值被修改時)。輸入參數通常傳值或常數引用(const references),輸出參數戒輸入/輸出參數爲很是數指針(non-const pointers)。對參數排序時,將全部輸入參數置於輸出參數以前。不要僅僅由於是新添加的參數,就將其置於最後,而應該依然置於輸出參數以前。這一點並非必須遵循的規則,輸入/輸出兩用參數(一般是類/結構體變量)混在其中,會使得規則難以遵照。
我的感覺:這條規則至關重要,本身寫代碼的時候可能沒有太大感受,可是在閱讀別人代碼的時候感受特別明顯。若是代碼按照這種規範來寫,從某種角度來講,這段代碼具備「自注釋」的功能,那麼在看代碼的時候就會比較輕鬆。Doom3的代碼規範中提到,「Use ‘const’ as much as possible」,也是一樣的意義。固然,const除了閱讀方便之外,還有個很重要的就是防止編碼錯誤,一旦在程序中修改const變量,編譯器就會報錯,這樣就減小了人工出錯了可能性,這點尤其重要!
包含文件的名稱及次序
將包含次序標準化可加強可讀性、避免隱藏依賴(hidden dependencies,注:隱藏依賴主要是指包含的文件編譯),次序以下:C 庫、C++庫、其餘庫的.h、項目內的.h。
項目內頭文件應挄照項目源代碼目錄樹結構排列,而且避免使用UNIX文件路徑.(當前目錄)和..(父目錄)。
舉例來講,google-awesome-project/src/foo/internal/fooserver.cc 的包含次序以下:
#include "foo/public/fooserver.h" // 優先位置
#include <sys/types.h>
#include <unistd.h>
#include <hash_map>
#include <vector>
#include "base/basictypes.h"
#include "base/commandlineflags.h"
#include "foo/public/bar.h"
注意,對應的頭文件必定要先包含,這樣避免隱藏依賴,隱藏依賴的問題不懂的能夠去Google,網上有不少資料。另外,《C++編程思想》中提到的包含次序正好相反,從特殊到通常,可是有一點和Google代碼規範是同樣的,那就是對應的頭文件是第一個包含。對於隱藏依賴的問題,之前只是習慣性的把對應的頭文件放第一個,沒有想過爲何,如今學習了……
做用域
全局變量
class 類型的全局變量是被禁止的,內建類型的全局變量是容許的,固然多線程代碼中很是數全局變量也是被禁止的。永遠不要使用函數返回值初始化全局變量。
不幸的是,全局變量的構造函數、析構函數以及初始化操做的調用順序只是被部分規定,每次生成有可能會有變化,從而致使難以發現bug。所以,禁止使用class類型的全局變量(包括STL的string,vector等),由於它們的初始化順序可能會致使出現問題。內建類型和由內建類型構成的沒有構造函數的結構體可使用,若是你必定要使用class類型的全局變量,請使用單件模式。
C++類
構造函數的職責
構造函數中只進行那些沒有實際意義的初始化,可能的話,使用Init()方法集中初始化爲有意義(non-trivial)的數據。
我的感覺:這種作法能夠從一開始就避免一些bug的出現,或更容易解決一些bug。構造函數+Init()函數初始化的方式與只用構造函數的方法相比,對計算機來講他們是沒有區別的,可是人是會犯錯的,這一條代碼規範在某種程度上避免了一些人爲錯誤,這個在開發中特別重要。
拷貝構造函數
僅在代碼中須要拷貝一個類的對象的時候使用拷貝構造函數,不須要拷貝時使用DISALLOW_COPY_AND_ASSIGN這個宏(關於這個宏的內容,能夠在網上搜到,我這裏就不寫了)。C++中對象的隱式拷貝是致使不少性能問題和bugs的根源。拷貝構造函數下降了代碼可讀性,相比按引用傳遞,跟蹤按值傳遞的對象更加困難,對象修改的地方變得難以捉摸。
我的感覺:和上一項的目的相似,爲了不人爲錯誤!拷貝構造函數原本是爲了方便程序員編程了,可是卻有可能成爲一個坑,爲了不這類問題,不須要拷貝時使用DISALLOW_COPY_AND_ASSIGN,這樣在須要調用拷貝構造函數的時候就會報錯,減小了人爲出錯的可能性。C#和Java在這方面就作得比較好,雖然性能上不如C++,可是人爲出錯的機率減小了不少。固然,使用必定的代碼規範,能夠在必定程度上減小C++的坑。
繼承
雖然C++的繼承很好用,可是在實際開發中,儘可能多用組合少用繼承,不懂的去看GoF的《Design Patterns》。
但重定義派生的虛函數時,在派生類中明確聲明其爲virtual。這一條是爲了爲了閱讀方便,雖然從語法的角度來講,在基類中聲明瞭virtual,子類能夠不用再聲明該函數爲virtual,但這樣一來閱讀代碼的人須要檢索類的全部祖先以肯定該函數是否爲虛函數o(╯□╰)o。
多重繼承
雖然容許,可是隻能一個基類有實現,其餘基類是接口,這樣一來和JAVA同樣了。這些東西在C#和JAVA中都進行了改進,直接從語法上解決問題。C++的靈活性太高,也是個麻煩的問題,只能經過代碼規範填坑。
接口
虛基類必須以Interface爲後綴,方便閱讀。閱讀方便。
重載操做符
除少數特定狀況外,不要重載操做符!!!「==」和「=」的操做Euqals和CopyFrom函數代替,這樣更直觀,也不容易出錯。
我的感覺:看到這一條,我有點驚訝,在學習C++的時候,說重載操做符有神馬神馬好處,爲何如今又說不要重載操做符呢?仔細看了他的文檔,確實說的有道理,致使可能出現的bug見其具體文檔。在實際應用中,因爲C++的坑實在太多了,不得不把這種「好用」的東西幹掉,由於出了bug又找不到,是一件很O疼的事情。
聲明次序
1)typedefs和enums;
2)常量;
3)構造函數;
4)析構函數;
5)成員函數,含靜態成員函數;
6)數據成員,含靜態數據成員。
宏 DISALLOW_COPY_AND_ASSIGN 置於private:塊以後,做爲類的最後部分。
其餘C++特性
引用參數
函數形參表中,全部的引用必須的const!
我的感覺:這麼作是爲了防止引用引發的誤解,由於引用在語法上是值,卻有指針的意義。雖然引用比較好用,可是犧牲其某些方面的特性,換來軟件管理方面的便利,仍是很值得了。
缺省參數
禁止使用函數缺省參數!
我的感覺:看到這一點的時候以爲有點因噎廢食了,其實缺省參數感受仍是蠻好用的。固然從另一個角度來講,要使用C++就不要怕這種小麻煩,若是由於使用這些特性形成了找不到的bug,那會損失更多時間。
異常
不要使用C++異常。
這一點我沒有看懂,也許是由於它的異常機制沒有C#和Java那麼完善吧……畢竟在C#和Java裏面異常仍是很好用的東東。
流
除了記錄日誌,不要使用流,使用printf之類的代替。
這一條實際上是有一些爭議的,固然大多數人認爲代碼一致性比較重要,因此選擇printf,具體的能夠看原文文檔。
const的使用
在任何能夠的狀況下都要使用const。
這條規則贊一個,Doom3的代碼規範裏也提到了這一條。這麼作有兩個好處,一個是防止程序出錯,由於修改了const類型的變量會報錯;另外一個就是方便閱讀,使代碼「自注釋」。雖然這麼作也有壞處,固然,整體來講利大於弊。
命名約定
一、整體規則:不要隨意縮寫,若是說 ChangeLocalValue 寫做ChgLocVal還有情可原的話,把ModifyPlayerName寫做MdfPlyNm就太過度了,除函數名可適當爲動詞外,其餘命名儘可能使用清晰易懂的名詞;
二、宏、枚舉等使用所有大寫+下劃線;
三、變量(含類、結構體成員變量)、文件、命名空間、存取函數等使用所有小寫+下劃線,類成員變量如下劃線結尾,全局變量以g_開頭;
四、普通函數、類型(含類與結構體、枚舉類型)、常量等使用大小寫混合,不含下劃線;
使用這套命名約定,可使代碼具備必定程度的「自注釋」功能,方便他人閱讀,也方便本身之後修改。固然三、4兩點也可使用其餘的命名約定,只要團隊統一便可。
格式
一、行寬原則上不超過80列,把22寸的顯示屏都佔完,怎麼也說不過去;
二、儘可能不使用非ASCII字符,若是使用的話,參考 UTF-8 格式(尤爲是 UNIX/Linux 下,Windows 下能夠考慮寬字符),儘可能不將字符串常量耦合到代碼中,好比獨立出資源文件,返不只僅是風格問題了;
三、UNIX/Linux下無條件使用空格,MSVC的話使用 Tab 也無可厚非; (我沒用過Linux,不懂爲何在Linux下無條件使用空格)
四、函數參數、邏輯條件、初始化列表:要麼全部參數和函數名放在同一行,要麼全部參數並排分行;
五、除函數定義的左大括號能夠置於行首外,包括函數/類/結極體/枚舉聲明、各類語句的左大括號置於行尾,全部右大括號獨立成行;
六、./->操做符先後丌留空格,*/&不要先後都留,一個就可,靠左靠右依各人喜愛;
七、預處理指令/命名空間不使用額外縮進,類/結構體/枚舉/函數/語句使用縮進;
八、初始化用=仍是()依我的喜愛,統一就好;
九、return不要加();
十、水平/垂直留白不要濫用,怎麼易讀怎麼來。
寫在最後
總的來講,這套代碼規範仍是至關不錯的,既有防止錯誤使用C++的某些特性而致使bugs的規範,又有代碼書寫的相關規範使其便於閱讀,建議搞C++的童鞋都看一看。固然,具體的團隊應該會有具體的代碼規範,代碼風格方面你們可能會有一些區別;不使用C++某些特性(好比不使用C++異常,禁止使用函數缺省參數)方面,應該按照具體狀況進行折中處理,而不該該生搬硬套代碼規範;可是「不將字符串常量耦合到代碼中」這種規範,是你們必須遵照的。