一迟隅、命名約定
最重要的一致性規(guī)則是命名管理梭纹。命名的風(fēng)格能讓我們在不需要去查找類型聲明的條件下快速地了解某個名字代表的含義:類型躲惰,變量,函數(shù)变抽,常量础拨,宏等等氮块,甚至我們大腦中的模式匹配引擎非常依賴這些命名規(guī)則。
命名規(guī)則具有一定隨意性诡宗,但相比按個人喜好命名滔蝉,一致性更重要,所以無論你認為它們是否重要僚焦,規(guī)則總歸是規(guī)則锰提。
二、通用命名規(guī)則
2.1 總述
函數(shù)命名芳悲,變量命名立肘,文件命名要有描述性;少用縮寫
名扛。
以達到“望文生義”
谅年,看其名,知其意肮韧。
2.2 說明
盡可能使用描述性的命名融蹂,別心疼空間,畢竟相比之下讓代碼易于新讀者理解更重要弄企。不要用只有項目開發(fā)者能理解的縮寫超燃,也不要通過砍掉幾個字母來縮寫單詞。
規(guī)范命名:
int price_count_reader; // 無縮寫
int num_errors; // "num" 是一個常見的寫法
int num_dns_connections; // 人人都知道 "DNS" 是什么
不規(guī)范命名:
int n; // 毫無意義
int nerr; // 含糊不清的縮寫
int n_comp_conns; // 含糊不清的縮寫
int wgc_connections; // 只有貴團隊知道是什么意思
int pc_reader; // "pc" 有太多可能的解釋了
int cstmr_id; // 刪減了若干字母
注意拘领,一些特定的廣為人知的縮寫是允許的意乓,例如用 i
表示迭代變量和用 T
表示模板參數(shù)。
三约素、命名體系
本文推薦3種命名體系届良,一個項目中只能選用一種,不得混用圣猎。
3.1 UNIX like體系
單詞用小寫字母士葫,每個單詞用下劃線 ”_”
分割。
舉例:
int number_of_bytes;
int success_flag;
int return_value;
3.2 Small-camel-case體系
小駝峰式命名送悔,除第一個單詞小寫
之外慢显,其他單詞首字母大寫
。
舉例:
int numberOfBytes;
int successFlag;
int returnValue;
3.3 Big-camel-case體系
大駝峰式命名欠啤,每個單詞首字母大寫
鳍怨。
舉例:
int NumberOfBytes;
int SuccessFlag;
int ReturnValue;
四、文件命名
4.1 總述
文件名要全部小寫
跪妥,可以包含下劃線 “_”
或連字符 “-”
, 依照項目的約定鞋喇。如果沒有約定,那么 “_”
更好眉撵。
4.2 說明
可接受的文件命名示例:
my_useful_class.cc
my-useful-class.cc
myusefulclass.cc
-
myusefulclass_test.cc
//_unittest
和_regtest
已棄用
原則上侦香,一個 .c
文件須有一個名稱相同的 .h
文件相對應(yīng)落塑。
C++ 文件要以 .cc
結(jié)尾,頭文件以 .h
結(jié)尾罐韩,定義類時文件名一般成對出現(xiàn), 如 foo_bar.h
和 foo_bar.cc
憾赁,對應(yīng)于類 FooBar
。
內(nèi)聯(lián)函數(shù)必須放在 .h
文件中散吵。如果內(nèi)聯(lián)函數(shù)比較短龙考,就直接放在 .h
中。
通常應(yīng)盡量讓文件名更加明確矾睦。http_server_logs.h
就比 logs.h
要好晦款。
五、類型命名
5.1 總述
類型名稱的每個單詞首字母均大寫枚冗,不包含下劃線: MyExcitingClass
缓溅,MyExcitingEnum
5.2 說明
所有類型命名——類,結(jié)構(gòu)體赁温,類型定義(typedef
)坛怪,枚舉,類型模板參數(shù)——均使用相同約定股囊,即以大寫字母
開始袜匿,每個單詞首字母均大寫
,不包含下劃線稚疹。
類名和對象名應(yīng)該是名詞或名詞短語沉帮。
舉例:
// 類和結(jié)構(gòu)體
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
// 類型定義
typedef hash_map<UrlTableProperties_t *, string> PropertiesMap;
// using 別名
using PropertiesMap = hash_map<UrlTableProperties_t *, string>;
// 枚舉
enum UrlTableErrors { ...
5.3 類型定義命名
/*
** 基本數(shù)據(jù)類型的重定義,小寫比首字母大寫更有利于延長Shift壽命贫堰,
** 但也更容易產(chǎn)生命名沖突。
*/
typedef unsigned char byte;
typedef unsigned char byte_t;
typedef unsigned char Byte;
typedef unsigned char Byte_t;
用 typedef
定義結(jié)構(gòu)體別名時待牵,首字母大寫
并加后綴 “_t”
舉例:
typedef struct
{
string name;
int num_entries;
static Pool<UrlTableProperties>* pool;
} UrlTableProperties_t;
5.4 類命名
定義一個類以 C
做為類名前綴其屏。
class CMyListCtrl;
六、變量命名
6.1 普通變量命名
- 變量(包括函數(shù)參數(shù))和數(shù)據(jù)成員名開頭字母一律
小寫
缨该,單詞之間可用下劃線連接偎行。 - 建議采用
Small-camel-case體系
舉例:
string table_name;
string tableName;
char* pTableName;
6.2 靜態(tài)變量命名
靜態(tài)變量增加 s_
作為前綴。
舉例:
int s_count;
int s_returnValue;
6.3 全局變量命名
全局變量增加 g_
作為前綴贰拿。
舉例:
int g_currentFile;
int g_username;
6.4 類數(shù)據(jù)成員命名
不管是靜態(tài)的還是非靜態(tài)的蛤袒,類數(shù)據(jù)成員都可以和普通變量一樣,但要接下劃線膨更。
class TableInfo
{
...
private:
string table_name_; // 好 - 后加下劃線
string tablename_; // 好
static Pool<TableInfo>* pool_; // 好
};
或者成員變量前加 m_
作為前綴妙真。
舉例:
string m_tableName;
6.5 結(jié)構(gòu)體變量命名
不管是靜態(tài)的還是非靜態(tài)的,結(jié)構(gòu)體數(shù)據(jù)成員都可以和普通變量一樣荚守,不用像類那樣接下劃線珍德。
struct UrlTableProperties
{
string name;
int num_entries;
static Pool<UrlTableProperties>* pool;
};
6.6 指針變量命名
對一重指針變量的基本原則為:p
+變量類型前綴+命名练般。
舉例:
char *pName;
對二重指針變量的基本規(guī)則為:pp
+變量類型前綴+命名。
對三重指針變量的基本規(guī)則為:ppp
+變量類型前綴+命名锈候。
七薄料、常量命名
7.1 總述
對于數(shù)值或者字符串等等常量的定義,建議采用全大寫
字母泵琳,單詞之間加 “_”
的方式命名(枚舉同樣建議使用此方式定義)
舉例:
const float PI_ROUNDED = 3.14;
7.2 說明
常量定義時盡量加 ’const’
修飾符
八摄职、宏命名
8.1 總述
對于數(shù)值或者字符串等等宏的定義,建議采用全大寫
字母获列,單詞之間加 “_”
的方式命名(枚舉同樣建議使用此方式定義)
舉例:
#define MAX_FILENAME_LENGTH 20
#define PI_ROUNDED 3.0
8.2 說明
- 宏定義表達式時要用完備的括號谷市,如:
#define RECTANGLE_AREA(a, b) a * b
以上定義存在風(fēng)險,以下定義才正確:
#define RECTANGLE_AREA(a, b) ((a) *( b))
- 將宏所定義的多條表達式放在大括號中蛛倦,如:
#define FOO(x) { \
printf("arg is %s\n", x); \
DoSomethingUseful(x); \
}
九歌懒、函數(shù)命名
9.1 總述
函數(shù)命名應(yīng)以函數(shù)要執(zhí)行的動作命名,一般采用動詞或者動詞+名詞的結(jié)構(gòu)溯壶。
舉例:
void DrawBox(int point);
9.2 說明
- 內(nèi)部或靜態(tài)函數(shù)采用
Small-camel-case體系
及皂,如:
void getBoxValue(void);
- 需要公開的函數(shù)(API)采用
Big-camel-case體系
,如:
void GetBoxValue(void);
- 對于首字母縮寫的單詞且改,更傾向于將它們視作一個單詞進行首字母大寫验烧,如:
void StartRpc(void);
而非
void StartRPC(void);
十、命名空間命名
命名空間以小寫字母命名慨蓝。最高級命名空間的名字取決于項目名稱感混。要注意避免嵌套命名空間的名字之間和常見的頂級命名空間的名字之間發(fā)生沖突。
頂級命名空間的名稱應(yīng)當(dāng)是項目名或者是該命名空間中的代碼所屬的團隊的名字。命名空間中的代碼庭呜,應(yīng)當(dāng)存放于和命名空間的名字匹配的文件夾或其子文件夾中募谎。
注意:不使用縮寫作為名稱
的規(guī)則同樣適用于命名空間。命名空間中的代碼極少需要涉及命名空間的名稱疯淫,因此沒有必要在命名空間中使用縮寫。
要避免嵌套的命名空間與常見的頂級命名空間發(fā)生名稱沖突。由于名稱查找規(guī)則的存在缆镣,命名空間之間的沖突完全有可能導(dǎo)致編譯失敗钠糊。尤其是,不要創(chuàng)建嵌套的 std
命名空間截珍。建議使用更獨特的項目標(biāo)識符 (websearch::index
, websearch::index_util
) 而非常見的極易發(fā)生沖突的名稱 (比如 websearch::util
)。
對于 internal
命名空間,要當(dāng)心加入到同一 internal
命名空間的代碼之間發(fā)生沖突 (由于內(nèi)部維護人員通常來自同一團隊鲸拥,因此常有可能導(dǎo)致沖突)撞叨。在這種情況下,請使用文件名以使得內(nèi)部名稱獨一無二 (例如對于 frobber.h
, 使用 websearch::index::frobber_internal
)
十一、枚舉命名
11.1 總述
枚舉的命名應(yīng)當(dāng)和常量
或宏
一致: kEnumName 或是 ENUM_NAME.
11.2 說明
單獨的枚舉值應(yīng)該優(yōu)先采用常量
的命名方式. 但宏
方式的命名也可以接受. 枚舉名 UrlTableErrors
(以及 AlternateUrlTableErrors
) 是類型, 所以要用大小寫混合的方式唉匾。
enum UrlTableErrors
{
kOK = 0,
kErrorOutOfMemory,
kErrorMalformedInput,
};
enum AlternateUrlTableErrors
{
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)格確實會產(chǎn)生編譯期問題典徘。
? 由 Leung 寫于 2019 年 4 月 18 日
? 參考:Google 開源項目風(fēng)格指南——7.命名約定
[逼死強迫癥 - C&C++設(shè)計風(fēng)格選擇.1] : 命名規(guī)范