C/C++該採用怎樣的命名規則才能讓自己的代碼足夠清晰呢?

如常量、函數、類之類的該怎麼命名才是比較好的呢?我現在編的都只是一些小程序,常用的只是簡單的sum val 之類的,但這樣顯然今後是不可行的。


C 的:

類型大寫首字母駝峰

變數和函數名小寫下劃線

常量大寫下劃線

駝峰和下劃線不混用

需要 export 的類型和函數加對應的駝峰/小寫下劃線前綴

前綴到處都有人人都知道可以縮寫, 後面部分盡量不要縮寫

我推薦多用下劃線沒什麼特別深刻原因: 因為閱讀需要空間

Web 語言也推薦下劃線. 因為RFC4343 規定了域名是不分大小寫的, url 的其他部分就各家有各家的玩法, 那請求參數還是用下劃線的比較保險. 然後你在語言里用駝峰的命名, 又天天處理各種請求參數, 就... 亂了...

JavaScript 為啥駝峰? 純粹歷史遺留問題, 這個語言已經沒救了


目前是IDE時代,匈牙利什麼的已經過時了。現在更應該講究可讀性並充分利用IDE的功能。

主要是大駝峰,跟C#的規則接近。

類名 CamelCase

  1. 介面類:I前綴,如 IClone

  2. 抽象類: Base前綴,如BaseActor

方法名CamelCase

Get/Set方法名:省略Get

float Width()const;

void SetWidth(float val);

一些返回結構引用可以:

const Size Size();

Size MutableSize();

bool類型的介面,一般用Is,Enable

bool IsEmpty()const;

void Enable(bool val);

局部或參數變數:camelCase

方法的輸出變數加out前綴,void GetSize(Size outSize);提醒這個變數之前的值並不重要

方法的輸入輸出變數加ref前綴,void GetSize(Size refSize); 提醒這個變數之前的值需要參與計算並改變後返回

成員變數:mCamelCase

這一點是跟大家都不太一樣的地方,大家一般都是用下劃線之類,但是我偏愛m,理由如下:

  1. 在方法實現中,一般需要一眼看出哪些是成員變數,哪些是局部變數,所以需要加區分。

  2. m比_更加的顯眼,對於戴眼鏡的程序員而言更加友好

  3. m隱含了member的意思

  4. m的敲鍵就在右手食指的挨著,而_你需要左手按住shift,再加上右手的右上角。m明顯要快得多。

  5. 有些人還喜歡m_CamelCase,但我認為中間的_是多此一舉了。

  6. Visual Assist自動生成Get,Set方法的時候也能夠自動識別m前綴,當然_也行。

宏:全大寫,並加模塊前綴,如MEDUSA_SIREN

枚舉盡量用enum class,名字CamelCase

如enum class Orientation

{

Left = 0,

Right,

Down,

Up,

};


只有一條,不要用下劃線,不然你的下劃線就跟C++那麼多運算符和符號攪在一起,簡直就看不明白到底誰是誰了。


對象_屬性_特徵 命名大法.

比如:

account_name //應為人可讀的字元串, 因為無特徵就是第一直覺

account_name_salted

account_name_id //id的特徵是唯一且數字化. 好比0012345這樣.


純 C

就我一個是

module_TypeName
module_functionName

這麼乾的么?


camelCase

PascalCase

underscore_case

_private_underscore_case

UPPERCASE_UNDERSCORE

不要用匈牙利命名法,那是為沒有IDE而且不面向對象的時代準備的,你在C++裡面遇到的大部分是對象,拿什麼前綴都是白費。camel還是下劃線僅僅是一個信仰的差異,Python推薦用下劃線是因為有_開頭是私有的約定,對Java和C++這樣有private和protected的功能的其實沒啥用,而且我到現在仍然覺得下劃線比camel丑……但終究來說,下劃線還是camel是個信仰問題。

其他的其實Python的約定挺合理的,類用PascalCase,全局常量用全部大寫的下劃線分割。局部變數盡量用比較短的表述。其他語言也都可以參考(而且實際上本來就是參考其他語言的規範制定的)


作為資深匈牙利命名法(10年+)的死忠轉用駝峰命名法,你們猜花了多久?

半個月

駝峰命名和帕斯卡命名法是當前lDE環境下最好的。

請參考《編寫可維護的JavaScript》一書


蟹妖。

我認為關鍵在於當事情變得複雜時,名字要長,以便和其它相似的功能區分開,比如:

recur_build_or_prepend_update_resp_parent_cache


被迫只能用C的時候,可以考慮#define PUBLIC #define PRIVATE 之類的.

還有 #define class struct 也是很好用的.

介面在每個文件頭部注釋裡面寫好用法.具體幹什麼 副作用都標出來.頭部沒寫的函數別從外邊調用.大概這樣.


C++要漂亮, 可以參考虛幻代碼。 不過有毒,小心。 我戒了三年


第一,這是寫純C的不是C++。

第二,可能某些規則有悖於主流想法,但是當大量統一使用的時候才能發現其中的美妙。

第三,每條規則都不是隨隨便便輕易決定的。規則之間互相的糾纏影響和對整體體驗都有著微妙的影響。

下面是規則。

1. 默認使用駝峰命名,除非指明使用下劃線分割

2. 變數名,首字母小寫

3. 函數指針變數,首字母大寫

4. 全局函數和結構體函數,首字母大寫

5. 結構體名,首字母大寫

6. 文件夾名,首字母大寫

7. 常量,枚舉,單詞小寫,下劃線分割

8. 宏定義語句,單詞大寫,下劃線分割

9. 宏定義標記,首字母小寫

10. 其它所有宏定義,單詞小寫,下劃線分割

11. 所有布爾值變數需要前綴 is

12. 所有返回布爾值函數需要前綴 Try

13. 所有單例變數需要前綴 A

14. goto 語句的標籤使用,單詞小寫,下劃線分割

15. 私有變數,兩端加下劃線

16. 只讀變數,前綴下劃線

17. 只寫變數,後綴下劃線

大概樣子具體可以參看一下,我用 C 實現解析Json字元串。


形式上的規則容易應用,也容易在不同風格間切換。

難的是如何用詞準確表達意圖,同時要熟悉相關概念的慣用語。這就要求你領域內的辭彙量要大,專業知識要紮實,工程實踐經驗更要豐富,缺一不可。之所以國內很多大牛的代碼難讀,就是因為命名表意模糊,甚至錯亂。


我的習慣是:

類名:AaaBbbCcc

方法名:AaaBbbCcc

成員變數:aaBbbCcc_

普通變數:aaBbbCcc


外界比較推崇的google 編碼規範可以參考。


google C++編碼規範

原文參見Google 開源項目風格指南 (中文版)

目前編寫50w行代碼,維護314w行代碼,整個項目1017萬行代碼。

血的教訓告訴你,編碼規範不應該是建議執行,而是需要嚴格執行,並且納入員工考核的重要KPI指標,否則代碼量會急劇膨脹到不可維護的階段……然後整個公司就歇菜了。

6.5. 常量命名

在全局或類里的常量名稱前加 k: kDaysInAWeek. 且除去開頭的 k 之外每個單詞開頭字母均大寫。

所有編譯時常量, 無論是局部的, 全局的還是類中的, 和其他變數稍微區別一下. k 後接大寫字母開頭的單詞:

const int kDaysInAWeek = 7;

這規則適用於編譯時的局部作用域常量,不過要按變數規則來命名也可以。

6.6. 函數命名

常規函數使用大小寫混合, 取值和設值函數則要求與變數名匹配: MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable().

常規函數:

函數名的每個單詞首字母大寫, 沒有下劃線。

如果您的某函數出錯時就要直接 crash, 那麼就在函數名加上 OrDie. 但這函數本身必須集成在產品代碼里,且平時也可能會出錯。

AddTableEntry()
DeleteUrl()
OpenFileOrDie()

取值和設值函數:

取值(Accessors)和設值(Mutators)函數要與存取的變數名匹配. 這兒摘錄一個類, num_entries_ 是該類的實例變數:

class MyClass {
public:
...
int num_entries() const { return num_entries_; }
void set_num_entries(int num_entries) { num_entries_ = num_entries; }

private:
int num_entries_;
};

其它非常短小的內聯函數名也可以用小寫字母, 例如. 如果你在循環中調用這樣的函數甚至都不用緩存其返回值, 小寫命名就可以接受.

6.3. 類型命名

類型名稱的每個單詞首字母均大寫, 不包含下劃線: MyExcitingClass, MyExcitingEnum.

所有類型命名 —— 類, 結構體, 類型定義 (typedef), 枚舉 —— 均使用相同約定. 例如:

// classes and structs
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...

// typedefs
typedef hash_map& PropertiesMap;

// enums
enum UrlTableErrors { ...


寫了幾年C++,變數名和函數名,用過小寫加下劃線,也用過小駝峰。過很久再看代碼,發現總是小駝峰清晰易懂。難怪Java的世界裡都是這種風格。所以以後堅持用小駝峰。


可以參考Google的code style


反正不要用匈牙利命名法,連微軟都開始不用了。


Google Style Guide. https://google.github.io/styleguide/cppguide.html


多看優秀的代碼,背 所有的死 規則只會使你 某守成規。


推薦閱讀:

如何才能學到Qt的精髓?
C++20有望實現自動PIMPL嗎?
如何評價 Herb Sutter 的 C++ 提案:metaclasses?
如何評價c++的協程庫libgo?
為什麼一般要用#include「xxx.h」?

TAG:程序員 | C編程語言 | C |