https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/naming/
最重要的一致性規(guī)則是命名管理. 命名的風(fēng)格能讓我們?cè)诓恍枰ゲ檎翌愋吐暶鞯臈l件下快速地了解某個(gè)名字代表的含義: 類型, 變量, 函數(shù), 常量, 宏, 等等, 甚至. 我們大腦中的模式匹配引擎非常依賴這些命名規(guī)則.
命名規(guī)則具有一定隨意性, 但相比按個(gè)人喜好命名, 一致性更重要, 所以無論你認(rèn)為它們是否重要, 規(guī)則總歸是規(guī)則.
7.1. 通用命名規(guī)則
總述
函數(shù)命名, 變量命名, 文件命名要有描述性; 少用縮寫.
說明
盡可能使用描述性的命名, 別心疼空間, 畢竟相比之下讓代碼易于新讀者理解更重要. 不要用只有項(xiàng)目開發(fā)者能理解的縮寫, 也不要通過砍掉幾個(gè)字母來縮寫單詞.
intprice_count_reader;// 無縮寫intnum_errors;// "num" 是一個(gè)常見的寫法intnum_dns_connections;// 人人都知道 "DNS" 是什么
intn;// 毫無意義.intnerr;// 含糊不清的縮寫.intn_comp_conns;// 含糊不清的縮寫.intwgc_connections;// 只有貴團(tuán)隊(duì)知道是什么意思.intpc_reader;// "pc" 有太多可能的解釋了.intcstmr_id;// 刪減了若干字母.
注意, 一些特定的廣為人知的縮寫是允許的, 例如用?i?表示迭代變量和用?T?表示模板參數(shù).
模板參數(shù)的命名應(yīng)當(dāng)遵循對(duì)應(yīng)的分類: 類型模板參數(shù)應(yīng)當(dāng)遵循?類型命名?的規(guī)則, 而非類型模板應(yīng)當(dāng)遵循?變量命名?的規(guī)則.
7.2. 文件命名
總述
文件名要全部小寫, 可以包含下劃線 (_) 或連字符 (-), 依照項(xiàng)目的約定. 如果沒有約定, 那么 “_” 更好.
說明
可接受的文件命名示例:
my_useful_class.cc
my-useful-class.cc
myusefulclass.cc
myusefulclass_test.cc?//?_unittest?和?_regtest?已棄用.
C++ 文件要以?.cc?結(jié)尾, 頭文件以?.h?結(jié)尾. 專門插入文本的文件則以?.inc?結(jié)尾, 參見?頭文件自足.
不要使用已經(jīng)存在于?/usr/include?下的文件名 (Yang.Y 注: 即編譯器搜索系統(tǒng)頭文件的路徑), 如?db.h.
通常應(yīng)盡量讓文件名更加明確.?http_server_logs.h?就比?logs.h?要好. 定義類時(shí)文件名一般成對(duì)出現(xiàn), 如?foo_bar.h?和?foo_bar.cc, 對(duì)應(yīng)于類?FooBar.
內(nèi)聯(lián)函數(shù)必須放在?.h?文件中. 如果內(nèi)聯(lián)函數(shù)比較短, 就直接放在?.h?中.
7.3. 類型命名
總述
類型名稱的每個(gè)單詞首字母均大寫, 不包含下劃線:?MyExcitingClass,?MyExcitingEnum.
說明
所有類型命名 —— 類, 結(jié)構(gòu)體, 類型定義 (typedef), 枚舉, 類型模板參數(shù) —— 均使用相同約定, 即以大寫字母開始, 每個(gè)單詞首字母均大寫, 不包含下劃線. 例如:
// 類和結(jié)構(gòu)體classUrlTable{...classUrlTableTester{...structUrlTableProperties{...// 類型定義typedefhash_map<UrlTableProperties*,string>PropertiesMap;// using 別名usingPropertiesMap=hash_map<UrlTableProperties*,string>;// 枚舉enumUrlTableErrors{...
7.4. 變量命名
總述
變量 (包括函數(shù)參數(shù)) 和數(shù)據(jù)成員名一律小寫, 單詞之間用下劃線連接. 類的成員變量以下劃線結(jié)尾, 但結(jié)構(gòu)體的就不用, 如:?a_local_variable,?a_struct_data_member,?a_class_data_member_.
說明
普通變量命名
舉例:
stringtable_name;// 好 - 用下劃線.stringtablename;// 好 - 全小寫.stringtableName;// 差 - 混合大小寫
類數(shù)據(jù)成員
不管是靜態(tài)的還是非靜態(tài)的, 類數(shù)據(jù)成員都可以和普通變量一樣, 但要接下劃線.
classTableInfo{...private:stringtable_name_;// 好 - 后加下劃線.stringtablename_;// 好.staticPool<TableInfo>*pool_;// 好.};
結(jié)構(gòu)體變量
不管是靜態(tài)的還是非靜態(tài)的, 結(jié)構(gòu)體數(shù)據(jù)成員都可以和普通變量一樣, 不用像類那樣接下劃線:
structUrlTableProperties{stringname;intnum_entries;staticPool<UrlTableProperties>*pool;};
結(jié)構(gòu)體與類的使用討論, 參考?結(jié)構(gòu)體 vs. 類.
7.5. 常量命名
總述
聲明為?constexpr?或?const?的變量, 或在程序運(yùn)行期間其值始終保持不變的, 命名時(shí)以 “k” 開頭, 大小寫混合. 例如:
constintkDaysInAWeek=7;
說明
所有具有靜態(tài)存儲(chǔ)類型的變量 (例如靜態(tài)變量或全局變量, 參見?存儲(chǔ)類型) 都應(yīng)當(dāng)以此方式命名. 對(duì)于其他存儲(chǔ)類型的變量, 如自動(dòng)變量等, 這條規(guī)則是可選的. 如果不采用這條規(guī)則, 就按照一般的變量命名規(guī)則.
7.6. 函數(shù)命名
總述
常規(guī)函數(shù)使用大小寫混合, 取值和設(shè)值函數(shù)則要求與變量名匹配:?MyExcitingFunction(),?MyExcitingMethod(),?my_exciting_member_variable(),?set_my_exciting_member_variable().
說明
一般來說, 函數(shù)名的每個(gè)單詞首字母大寫 (即 “駝峰變量名” 或 “帕斯卡變量名”), 沒有下劃線. 對(duì)于首字母縮寫的單詞, 更傾向于將它們視作一個(gè)單詞進(jìn)行首字母大寫 (例如, 寫作?StartRpc()?而非?StartRPC()).
AddTableEntry()DeleteUrl()OpenFileOrDie()
(同樣的命名規(guī)則同時(shí)適用于類作用域與命名空間作用域的常量, 因?yàn)樗鼈兪亲鳛?API 的一部分暴露對(duì)外的, 因此應(yīng)當(dāng)讓它們看起來像是一個(gè)函數(shù), 因?yàn)樵谶@時(shí), 它們實(shí)際上是一個(gè)對(duì)象而非函數(shù)的這一事實(shí)對(duì)外不過是一個(gè)無關(guān)緊要的實(shí)現(xiàn)細(xì)節(jié).)
取值和設(shè)值函數(shù)的命名與變量一致. 一般來說它們的名稱與實(shí)際的成員變量對(duì)應(yīng), 但并不強(qiáng)制要求. 例如?int?count()?與?void?set_count(int?count).
7.7. 命名空間命名
總述
命名空間以小寫字母命名. 最高級(jí)命名空間的名字取決于項(xiàng)目名稱. 要注意避免嵌套命名空間的名字之間和常見的頂級(jí)命名空間的名字之間發(fā)生沖突.
頂級(jí)命名空間的名稱應(yīng)當(dāng)是項(xiàng)目名或者是該命名空間中的代碼所屬的團(tuán)隊(duì)的名字. 命名空間中的代碼, 應(yīng)當(dāng)存放于和命名空間的名字匹配的文件夾或其子文件夾中.
注意?不使用縮寫作為名稱?的規(guī)則同樣適用于命名空間. 命名空間中的代碼極少需要涉及命名空間的名稱, 因此沒有必要在命名空間中使用縮寫.
要避免嵌套的命名空間與常見的頂級(jí)命名空間發(fā)生名稱沖突. 由于名稱查找規(guī)則的存在, 命名空間之間的沖突完全有可能導(dǎo)致編譯失敗. 尤其是, 不要?jiǎng)?chuàng)建嵌套的?std?命名空間. 建議使用更獨(dú)特的項(xiàng)目標(biāo)識(shí)符 (websearch::index,?websearch::index_util) 而非常見的極易發(fā)生沖突的名稱 (比如?websearch::util).
對(duì)于?internal?命名空間, 要當(dāng)心加入到同一?internal?命名空間的代碼之間發(fā)生沖突 (由于內(nèi)部維護(hù)人員通常來自同一團(tuán)隊(duì), 因此常有可能導(dǎo)致沖突). 在這種情況下, 請(qǐng)使用文件名以使得內(nèi)部名稱獨(dú)一無二 (例如對(duì)于?frobber.h, 使用?websearch::index::frobber_internal).
7.8. 枚舉命名
總述
枚舉的命名應(yīng)當(dāng)和?常量?或?宏?一致:?kEnumName?或是?ENUM_NAME.
說明
單獨(dú)的枚舉值應(yīng)該優(yōu)先采用?常量?的命名方式. 但?宏?方式的命名也可以接受. 枚舉名?UrlTableErrors(以及?AlternateUrlTableErrors) 是類型, 所以要用大小寫混合的方式.
enumUrlTableErrors{kOK=0,kErrorOutOfMemory,kErrorMalformedInput,};enumAlternateUrlTableErrors{OK=0,OUT_OF_MEMORY=1,MALFORMED_INPUT=2,};
2009 年 1 月之前, 我們一直建議采用?宏?的方式命名枚舉值. 由于枚舉值和宏之間的命名沖突, 直接導(dǎo)致了很多問題. 由此, 這里改為優(yōu)先選擇常量風(fēng)格的命名方式. 新代碼應(yīng)該盡可能優(yōu)先使用常量風(fēng)格. 但是老代碼沒必要切換到常量風(fēng)格, 除非宏風(fēng)格確實(shí)會(huì)產(chǎn)生編譯期問題.
7.9. 宏命名
總述
你并不打算?使用宏, 對(duì)吧? 如果你一定要用, 像這樣命名:?MY_MACRO_THAT_SCARES_SMALL_CHILDREN.
說明
參考?預(yù)處理宏; 通常?不應(yīng)該?使用宏. 如果不得不用, 其命名像枚舉命名一樣全部大寫, 使用下劃線:
#define ROUND(x) ...#define PI_ROUNDED 3.0
7.10. 命名規(guī)則的特例
總述
如果你命名的實(shí)體與已有 C/C++ 實(shí)體相似, 可參考現(xiàn)有命名策略.
bigopen(): 函數(shù)名, 參照?open()?的形式
uint:?typedef
bigpos:?struct?或?class, 參照?pos?的形式
sparse_hash_map: STL 型實(shí)體; 參照 STL 命名約定
LONGLONG_MAX: 常量, 如同?INT_MAX
譯者(acgtyrant)筆記
感覺 Google 的命名約定很高明, 比如寫了簡(jiǎn)單的類 QueryResult, 接著又可以直接定義一個(gè)變量 query_result, 區(qū)分度很好; 再次, 類內(nèi)變量以下劃線結(jié)尾, 那么就可以直接傳入同名的形參, 比如?TextQuery::TextQuery(std::string?word)?:?word_(word)?{}?, 其中?word_?自然是類內(nèi)私有成員.