翻譯】geosoft C++ Programming Style Guideline

Version:1.0StartHTML:000000230EndHTML:000055203StartFragment:000002412EndFragment:000055129StartSelection:000002434EndSelection:000055113SourceURL:https://www.cnblogs.com/amaoxiaozhu/archive/2012/02/29/2373141.html

翻譯】geosoft C++ Programming Style Guidelines (已翻譯完畢雾家,大家看看自己總結(jié)出了哪些吧=)

REF :http://geosoft.no/development/cppstyle.html

原文鏈接:https://www.cnblogs.com/amaoxiaozhu/archive/2012/02/29/2373141.html

如有侵權(quán)到腥,請及時聯(lián)系,立即刪除茎用。

個人意譯-大家可以隨時拍磚討論心得!^)

24屋确、29 瘤睹、53、 57 求助 `~`


1 介紹

  這份文檔羅列了C++ 開發(fā)社區(qū)中基本相同的編程指導(dǎo)番电。

指導(dǎo)是基于大量的代碼岗屏、個人經(jīng)驗、實際需求及其他資料中的建議[1]-[4]

使用一份新的指導(dǎo)而不是引用這些資料中主要的原因就是這些這些指導(dǎo)過于寬泛漱办,我們需要更加具體的規(guī)則(尤其是命名方面)这刷。同樣,整個指導(dǎo)把規(guī)則增加了注釋娩井,使得在代碼審計中要比之前的規(guī)則指導(dǎo)易于使用暇屋。值得一提的是,編程指導(dǎo)中包含著許許多多方面洞辣,這份文檔集中在代碼規(guī)則上咐刨,其他可以參考C++ Programming Practice Guidelines.

IDE提供了代碼隱藏、上色和自動格式化等等功能扬霜,但程序員不應(yīng)該依靠這些特性定鸟。源代碼不應(yīng)當局限在當前正在使用的IDE中,而是在寫代碼時要使他盡量能夠在任何類型的IDE下都可以清晰的閱讀


1.1 指南的樣式

指南以話題的形式組合,并且每個指南都有一個可以用于引用的標號

n. 指南簡單描述

可能的例子

原因著瓶、背景联予、附加信息

第三段很重要,代碼編寫標準通常會引起“圣戰(zhàn)” 標注出每種標注的使用背景就很重要了:)

1.2 指南的重要性

在指南里,分為必須沸久、應(yīng)該和推薦三種等級季眷。

2 通用指南

1. 任何違反本指南但提高代碼閱讀性的方法都是允許的


指南的主要目的就是增加代碼的可讀性,提供代碼質(zhì)量卷胯。讓代碼更好的被理解和維護子刮。在這種指南中對于特殊情況的事件是無法包括的,需要程序員靈活的運用窑睁。


2.如果個人不喜歡這種方式挺峡,可以違背指南


制作這份文檔的目的是為了指南,而不是規(guī)定一種必需人人遵守的規(guī)則卵慰。有經(jīng)驗的程序員通常有自己的一種類似于本指南的方法沙郭。但有這樣一份指南,當需要人來所熟悉裳朋、理解它病线,通常可以使人們考慮編程的方法鲤嫡,評估他們自己在這一領(lǐng)域的習(xí)慣送挑。

另一方面來說,對于新程序員和尚缺少經(jīng)驗的程序員們想要更快的進入編程這個行業(yè)中暖眼,遵循一份代碼指南是一條方便惕耕、簡單的道路

3 命名慣例

3.1 常見的命名慣例

3. 命名變量類型時必須用起始字母大寫的單詞

Line, SavingsAccount

Common practice in the C++ development community.????????????


4.?變量必須的起始字母小寫

line, savingsAccount

Common practice in the C++ development community. 使得變量與類型可以清晰的分辨,也解決了變量與類型名的沖突

Line line


5. 命名常量應(yīng)當使用全大寫字母诫肠,單詞之間使用下劃線連接

MAX_ITERATIONS, COLOR_RED, PI

Common practice in the C++ development community. 通常情況下司澎,常量的使用應(yīng)該控制在最小限度內(nèi),在很多情況下可以把值變?yōu)榉椒ǎ?/p>

? int getMaxIterations() // NOT: MAX_ITERATIONS = 25

? {

? ? return 25;

? }

這樣既清晰閱讀栋豫,又確保了這個接口對于類來說值是統(tǒng)一的挤安。


6. 命名函數(shù)時一定要使用動詞并且起始字母小寫。

getName(), computeTotalWidth()

C++社區(qū)常用規(guī)范丧鸯。 與命名變量類似,但是C++中的函數(shù)可以被它自己的特有的方式識別出來蛤铜。


7. 命名空間應(yīng)該使用小寫

model::analyzer, io::iomanager, common::math::geometry

C++社區(qū)常用規(guī)范。


8. 命名模板類型應(yīng)該使用一個單一的大寫字母丛肢。

template<class T> ... template<class C, class D> ...

C++社區(qū)常用規(guī)范围肥。?這樣使得模板名稱與其他使用的名稱清晰的獨立出來


9. 簡略詞必須不使用全大寫

exportHtmlSource();// NOT: exportHTMLSource();

openDvdPlayer();// NOT: openDVDPlayer();

使用全大寫的縮略詞會導(dǎo)致沖突,像dVD,hTML這類的同樣也不利于閱讀蜂怎,而且當略縮詞后面連接了一個單詞后穆刻,會減少后面單詞的可讀性。


10. 全局變量應(yīng)當使用操作符::

::mainWindow.open(), ::applicationContext.getName()

通常應(yīng)該避免使用全局變量杠步,考慮單間模式的對象來代替氢伟。


11. 私有類變量應(yīng)該使用下劃線字尾.

class SomeClass { private: int length_; }

除了變量的名稱和類型撰洗,作用域是一個變量最重要的屬性。?its name and its type, thescopeof a variable is its most important feature.?通過下劃線來區(qū)分局部變量和類的私有變量是很方便的事情腐芍。因為類變量具有比函數(shù)變量更大的作用域因此應(yīng)當值得程序員的注意。

同時還使得當變量出現(xiàn)問題時试躏,更方便的解決猪勇。

void setDepth (int depth)

{

depth_ = depth;

}

這種方案的一個問題就是應(yīng)當使用下劃線做前綴還是后綴,這兩種方法都被廣泛的應(yīng)用颠蕴,但后綴更加值得推薦一下泣刹,因為我們覺得這樣使得單詞看起來更舒服。

值得注意的是變量作用域標識的問題已經(jīng)有很長時間了犀被,這個指南中這條規(guī)則被更多的應(yīng)用了椅您。


12.? 通用的變量名應(yīng)該與類型名一致

void setTopic(Topic* topic)// NOT: void setTopic(Topic* value)// NOT: void setTopic(Topic* aTopic)// NOT: void setTopic(Topic* t)

void connect(Database* database)// NOT: void connect(Database* db)// NOT: void connect (Database* oracleDB)

通過減少不同變量名等方法來減少代碼的復(fù)雜度,同樣使得通過變量名猜測變量類型變得容易寡键。

如果某些情況下無法滿足這條指南掀泳,非通用的變量會有一個特殊的角色,那么這些變量可以把角色和類型聯(lián)合起來:

Point? startingPoint, centerPoint;

Name?? loginName;


13. 所有名稱應(yīng)該使用英語

fileName;// NOT: filNavn

在國際化開發(fā)中西轩,英語是首推語言员舵。


14. 變量的作用域長,使用長變量名藕畔,變量作用域短马僻,使用短變量名。


用于短暫存儲或序號等的臨時變量應(yīng)該盡量保持簡單注服。一個程序員在讀到這些變量就可以推斷出變量的值不會在外部使用韭邓,而且只是作用于很少行代碼。常見的臨時變量有:整數(shù):i溶弟、j女淑、k、m可很、n 字符: c诗力、d


15. 對象名是一種暗示,應(yīng)該避免再次出現(xiàn)在方法中

line.getLength();// NOT: line.getLineLength();

在類定義時函數(shù)看起來似乎正常我抠,但在上例中可以看的很清楚苇本,多余了。



3.2 特定的命名指南

17. 當一個屬性被允許修改菜拓,那么必須要通過使用get/set函數(shù)

employee.getName();

employee.setName(name);

matrix.getElement(2, 4);

matrix.setElement(2, 4, value);

C++社區(qū)常用規(guī)范瓣窄。在java中,這已經(jīng)基本變成了一種標準纳鼎。


18. 可以使用compute命名需要在函數(shù)內(nèi)進行計算的函數(shù)

valueSet->computeAverage();

matrix->computeInverse()

給閱讀代碼者一個清晰的認識俺夕,這里是一個潛在的消耗時間的操作裳凸,當需要重復(fù)時,就可以考慮緩存函數(shù)執(zhí)行結(jié)果劝贸。一致的使用這種命名方式可以提高代碼的可讀性姨谷。


19. 可以使用find命名需要在函數(shù)內(nèi)進行查找的函數(shù)

vertex.findNearestVertex();

?matrix.findMinElement();

給閱讀代碼者一個清晰的認識,這是一個僅僅為了查找的操作映九,這種函數(shù)使用最少的操作梦湘。一致的使用這種命名方式可以提供代碼的可讀性。


20.initialize可以用來命名一個對象或強模板的建立件甥。

printer.initializeFontSet();

美式的initialize要比英式的initialise好. 不應(yīng)該使用略縮詞init


21. 代表著可視化組件的變量捌议,應(yīng)該具有組件類型的后綴名。

mainWindow, propertiesDialog, widthScale, loginText,

leftScrollbar, mainForm, fileMenu, minLabel, exitButton, yesToggle etc.

增加可讀性引有,可以直觀的看出變量類型和對象資源瓣颅。


22. 當表示多個對象時,應(yīng)該使用復(fù)數(shù)形式譬正。

vector<Point> points; int values[];

增加可讀性宫补,可以直觀的看出變量類型和可以應(yīng)用于此種類型的操作。


23. 當表示多個對象的個數(shù)時导帝,應(yīng)該使用前綴n

nPoints, nLines

在數(shù)學(xué)界中表示對象數(shù)目的方式守谓。


24.當表示一個實體的序號時,應(yīng)該使用后綴

tableNo, employeeNo

在數(shù)學(xué)界中表示實體的方式您单。

一種優(yōu)雅的替換方式是使用前綴i:iTable斋荞, iEmployee。在迭代器中使用虐秦。(This effectively makes themnamediterators. )


25. 迭代器中的變量應(yīng)該起名為i平酿、j、k等

for (int i = 0; i < nTables); i++) { : }

?for (vector<MyClass>::iterator i = list.begin(); i != list.end(); i++)

? ?{ Element element = *i; ... }

在數(shù)學(xué)界中表示迭代變量的方式悦陋。

變量名為j蜈彼、k等變量,應(yīng)該只在緊湊的循環(huán)中使用俺驶。


26. 前綴is應(yīng)該在布爾變量或返回布爾值的函數(shù)中使用幸逆。

isSet, isVisible, isFinished, isFound, isOpen

C++社區(qū)通用規(guī)范 及 java部分強制需求。

使用is前綴解決了一個常見的布爾變量命名問題暮现,使用stauts还绘、flag通常是比較差的布爾變量名。

有一些替換的變量前綴可能更加使用:has栖袋、can和should:

? bool hasLicense();

? bool canEvaluate();

? bool shouldSort();


27. 互補的名字必須用于互補的操作

get/set, add/remove, create/destroy, start/stop, insert/delete,

increment/decrement,old/new, begin/end, first/last, up/down,

min/max, next/previous, old/new, open/close, show/hide, suspend/resume

通過對稱減少復(fù)雜性


28. 應(yīng)該避免縮寫

computeAverage();// NOT: compAvg();

有兩類單詞拍顷,一類是經(jīng)常會被使用的單詞,永遠不要縮寫他們:

cmd?? instead of? command

cp ?? instead of? copy

pt ?? instead of? point

comp? instead of? compute

init? instead of? initialize

還有一類是具有特殊含義的短語塘幅,基本被所有人所熟知昔案,要使用這種縮寫:

HypertextMarkupLanguage?instead of? html

CentralProcessingUnit ??instead of? cpu

PriceEarningRatio ?? ? ?instead of? pe


29. 對于指針的特殊命名應(yīng)該避免

Line* line;// NOT: Line* pLine; // NOT: LIne* linePtr;

在C/C++ 環(huán)境中尿贫,許多變量都是指針,因此許多約定都無法遵守踏揣。同樣在C++中對象經(jīng)常不具有明顯的類型庆亡,程序員應(yīng)該避免特殊的實習(xí)。只有當一個對象的實際類型特別重要時捞稿,變量名才應(yīng)該著重它的類型身冀。(Many variables in a C/C++ environment are pointers, so a convention like this is almost impossible to follow. Also objects in C++ are often oblique types where the specific implementation should be ignored by the programmer. Only when the actual type of an object is of special significance, the name should emphasize the type. )


30. 必須避免否定的布爾變量名

bool isError;// NOT: isNoErrorbool

isFound;// NOT: isNotFound

這樣做的問題是在邏輯判斷中使用了雙重否定無法第一時間判斷出含義:!isNotFound


31. 枚舉常量應(yīng)具有一個共同的前綴類型名

enum Color { COLOR_RED, COLOR_GREEN, COLOR_BLUE };

這樣命名增加了額外信息,哪里可以找到這些變量括享、哪幾種常量是一起的以及代表了什么樣的內(nèi)容。

一種替代方式是保持通過類型進行引用Color::RED,Airline::AIR_FRANCE

注意枚舉類型的變量名應(yīng)該是單數(shù)形式enum Color {...}.一個復(fù)數(shù)的名字盡管看起來沒有什么區(qū)別珍促,但在使用時看起來非常愚蠢铃辖。


32. 異常函數(shù)應(yīng)當具有后綴Exception.

class AccessException { : }

異常函數(shù)不應(yīng)該作為程序的主要設(shè)計部分,如此命名使得它遠離其他的函數(shù)猪叙。


33. 函數(shù)(方法具有返回值)應(yīng)當被命名為他們返回的事物娇斩,過程(方法返回為空)應(yīng)該被命名為做了何事。


增加可讀性穴翩,使得可以清晰的看到這個單元應(yīng)該怎么用特別是什么不支持犬第。這同樣使得它避免了邊界效應(yīng)的影響。


4?文件

4.1?源文件

1

34. C++的頭文件應(yīng)該具有.h(推薦)或.hpp的擴展名

源文件應(yīng)該具有.c++芒帕、.C歉嗓、.cc或.cpp的擴展名

MyClass.c++,

MyClass.h

符合C++文件擴展標準


35. 一個類應(yīng)該聲明在頭文件中,定義在與類名相同的源文件中背蟆。

MyClass.h,

MyClass.c++

容易找到某個給定的類鉴分,例外是模板類必須在.h文件中聲明和定義。


36. 所有的定義都應(yīng)該在源文件中带膀。

class MyClass

{

???????? public: int getValue ()

{return value_;}// NO!... private: int value_; }

頭文件中應(yīng)該聲明一個接口志珍,源文件中實現(xiàn)這個接口。當查找一個具體的實現(xiàn)代碼時垛叨,那么我們就知道可以在源文件中找到伦糯。


37. 文件的內(nèi)容必須保持在80列以內(nèi)


80列是編輯器、終端嗽元、打印機敛纲、調(diào)試器中常見的寬度,文件在幾個人之間傳看應(yīng)該保證這些約束还棱。在代碼傳遞時避免了被動斷行载慈,可以提高代碼的可讀性。?


38. 像TAB 和 分頁符一類的特殊字符必須避免使用


在多環(huán)境珍手、多人編程時办铡,這類字符一定會導(dǎo)致編輯器辞做、打印機、終端或調(diào)試器的問題寡具。


39. 必須讓分行的代碼顯示明顯

totalSum = a + b + c +

????????????????d + e;

function (param1, param2,

?????????????param3);

setText ("Long line split"

????????????"into two parts.");

for (int tableNo = 0; tableNo < nTables;

???? tableNo += tableStep)

?{

?????? ?...

?}

當一段代碼超過80列需要進行分行秤茅,很難給出嚴格的規(guī)定何時進行分行,以上例子可以作為參考

通常:

在逗號后面分行

在操作符后面分行

新行對其前一行的表達式開頭童叠。

4.2 Include

40. 頭文件必須要包含一個頭文件守護

#ifndef COM_COMPANY_MODULE_CLASSNAME_H

#define COM_COMPANY_MODULE_CLASSNAME_H :

#endif // COM_COMPANY_MODULE_CLASSNAME_H

這樣的語法結(jié)構(gòu)用來避免編譯錯誤框喳。這樣命名統(tǒng)一了頭文件出現(xiàn)在源文件中的位置,避免了名字沖突厦坛。


41. Include語句應(yīng)當按組排列五垮,按照在系統(tǒng)中的位置進行排序,低等級的在最前方聲明杜秸,每個組之間保留一個空行放仗。

#include <fstream>

#include <iomanip>


#include <qt/qbutton.h>

#include <qt/qtextfield.h>


#include "com/company/ui/PropertiesDialog.h"

#include "com/company/ui/MainWindow.h"

除了可以給讀者一個清晰的包含文件的結(jié)構(gòu),還可以直觀的看出使用了哪些模塊撬碟。

包含文件的路徑永遠不要使用絕對路徑诞挨,編譯器的指令才應(yīng)用來指定包含文件的根目錄。


42. Include語句必須只在文件的頂部


通用規(guī)范呢蛤。避免了邊界影響惶傻。當include聲明在源代碼中的某處時,可能會忽略它所帶來的影響其障。


5 語句

5.1 類型

43. 在文件內(nèi)部使用的變量應(yīng)該在文件里面進行聲明银室。


確保了信息隱藏


44. 類一定要按照public、protected和private的順序來聲明励翼。每種類型必須要精確的組織出來粮揉,不應(yīng)當有混合情況。(All sections must be identifiedexplicitly. Not applicable sections should be left out. )


順序就是最常用的放到第一位抚笔,這樣當需要使用這個類時扶认,可以在讀到代碼段protected或private時停止。


45. 類型轉(zhuǎn)換必須要表示出來,不要依靠隱藏的類型轉(zhuǎn)換

floatValue = static_cast(intValue);// NOT: floatValue = intValue;

這樣程序員表面了他意識到了不同類型的轉(zhuǎn)換殊橙,而需要進行辐宾。

5.2 變量

46. 變量應(yīng)當在聲明時被初始化。


這樣確保了變量隨時都是可用的膨蛮。但當聲明時無法確定初始值:

int x, y, z;

getCenter(&x, &y, &z);

就應(yīng)當保持未初始化的狀態(tài)叠纹,而不是初始化一些莫名奇妙的值。


47. 變量不應(yīng)當具有雙重意義敞葛。


確保所有的概念都通過唯一的變量代表誉察,不僅提供了可讀性,還可用減少副作用帶來的錯誤惹谐。


48. 全局變量的應(yīng)用應(yīng)該保持在最小化的范圍持偏。


在C++中沒有使用全局變量驼卖、全局函數(shù)或作用整個文件內(nèi)變量的理由。


49. 類變量不應(yīng)當被聲明為public


public變量會破壞C++的信息隱藏和抽象鸿秆。使用私有變量和訪問函數(shù)來代替酌畜。有一種例外情況是當類像C中的結(jié)構(gòu)體一樣時,只包含數(shù)據(jù)卿叽。

值得注意結(jié)構(gòu)體在C++中只是為了與C語言的兼容性桥胞,因此應(yīng)當盡量不使用struct而是用類。


51. C++ pointers and references should have their reference symbol next to the type rather than to the name.

float* x;// NOT: float *x; int& y;// NOT: int &y;

Thepointer-nessorreference-nessof a variable is a property of the type rather than the name. C-programmers often use the alternative approach, while in C++ it has become more common to follow this recommendation.

53. 除了布爾變量及指針外考婴,不應(yīng)該隱式的比較0

if (nLines != 0)// NOT: if (nLines)

if (value != 0.0)// NOT: if (value)

翻譯不通贩虾、It is not necessarily defined by the C++ standard that ints and floats 0 are implemented as binary 0. Also, by using an explicit test the statement gives an immediate clue of the type being tested.

It is common also to suggest that pointers shouldn't test implicitly for 0 either, i.e.if (line == 0)instead ofif (line). The latter is regarded so common in C/C++ however that it can be used.

54. 變量應(yīng)當在最小的域內(nèi)聲明。


在一個范圍內(nèi)保持變量的操作沥阱,這樣做可以控制變量的影響和副作用整胃。

5.3 循環(huán)

55. 在for語句中只包括控制語句。

sum = 0;// NOT: for (i = 0, sum = 0; i < 100; i++)

for (i = 0; i < 100; i++)??????????????????????????? sum += value[i];

sum += value[i];


增加維護性和可讀性喳钟。一個清晰的控制信息和循環(huán)中包含的條件。


56.循環(huán)變量應(yīng)該在循環(huán)開始前初始化在岂。

isDone = false;// NOT: bool isDone = false;

while (!isDone) {//???????? :

://????????? while (!isDone) {

}//????????? ?:

???????????????????????????? //?????????????}


57. 應(yīng)當避免使用do-while循環(huán)


do-while循環(huán)的控制條件在底部奔则,可讀性差。讀者需要瀏覽完整個循環(huán)才能看到循環(huán)的范圍蔽午。

另外易茬,do-while循環(huán)沒有什么理由出現(xiàn),任何do-while都可以簡單的重寫成while循環(huán)或for循環(huán)及老。減少這類使用提供可讀性抽莱。(Reducing the number of constructs used enhance readbility. )

58. 應(yīng)當避免在循環(huán)中使用break和continue語句。


只有他們比完成同樣功能的結(jié)構(gòu)化代碼提供更清晰的可讀性時才應(yīng)當被使用骄恶。


60. 在無限循環(huán)中應(yīng)當使用while(true)

while (true)

?{

?:

}

for (;;) { // NO!

:

}

while (1) { // NO!

:

}

測試1既不是必要的也沒有意義食铐。for(;;)可讀性不強,也不能清晰表明自己是一個無限循環(huán)僧鲁。

5.4 條件語句

61. 復(fù)雜的條件判斷必須避免虐呻,使用臨時的布爾變量保存

bool isFinished = (elementNo < 0) || (elementNo > maxElement);

bool isRepeatedEntry = elementNo == lastElement;

if (isFinished || isRepeatedEntry) {?

? :

}

// NOT: if ((elementNo < 0) || (elementNo > maxElement)|| elementNo == lastElement)

??{

:

}

使用布爾變量,程序可以自解釋寞秃,容易閱讀斟叼、調(diào)試和維護。


62. 在if語句中春寿,更常見的實例應(yīng)當放在if中朗涩,例外放在else中。

bool isOk = readFile (fileName);

if (isOk) {

?:

?} else {

?:

?}

確保例外的事件沒有在正常的路徑上绑改。對于可讀性和代碼性能都有影響谢床。


63. 條件語句應(yīng)該放在單獨一行中兄一。

if (isDone)// NOT: if (isDone) doCleanup();

?? doCleanup();

為了調(diào)試方便,寫在同一行中萤悴,無法清楚的知道結(jié)果是真還是假瘾腰。


64. 在判斷中使用執(zhí)行語句的返回值必須被避免

File* fileHandle = open(fileName, "w");

if (!fileHandle) {

?:

}// NOT: if (!(fileHandle = open(fileName, "w"))) { : }

可執(zhí)行語句的作為條件難以閱讀,尤其是C/C++的新手覆履。

5.5 雜項

65. 應(yīng)該避免魔數(shù)的使用蹋盆,除了0、1硝全,應(yīng)當考慮聲明常量來代替栖雾。


當一個數(shù)字無法表述自己的含義時,采用命名常量來提高代碼的可讀性伟众。另一種做法是在使用這個數(shù)字時析藕,寫一個函數(shù)。


66. 浮點常數(shù)應(yīng)當帶有小數(shù)點和至少一位小數(shù)凳厢。

double total = 0.0;// NOT: double total = 0;

double speed = 3.0e8;// NOT: double speed = 3e8;

double sum;

:

sum = (a + b) * 10.0;

強調(diào)了整數(shù)與浮點數(shù)的區(qū)別账胧,同樣,像最后的例子里先紫,他表達了變量(sum)的類型治泥,這僅僅從(a+b)中是無法看出來的。


67. 浮點常數(shù)應(yīng)當在小數(shù)點前面包含一個數(shù)字遮精。

double total = 0.5;// NOT: double total = .5;

數(shù)字和表達方式借鑒于數(shù)學(xué)居夹,所以應(yīng)當盡量滿足數(shù)學(xué)的語法。同樣本冲,0.5比.5具有更高的可讀性准脂,也不會使人看成是5


68. 函數(shù)一定要有返回值的類型。

int getValue()// NOT: getValue(){ : }

如果沒有指示檬洞,那么C++會將int作為函數(shù)返回類型狸膏。程序員不應(yīng)當依靠這種特性,它會使程序員迷惑于是否具有這種特性添怔。( since this might be confusing for programmers not aware of this artifact. )


69. 不應(yīng)當使用goto語句


Goto語句破壞了結(jié)構(gòu)化的代碼环戈,只有在非常少的情況下(跳出一個深層的結(jié)構(gòu))才應(yīng)該考慮使用纲辽,而且要保證類似的實習(xí)會導(dǎo)致閱讀性下降着裹。


70. 使用“0”而不是"NULL"


NULL是C標準庫中的候醒,在C++中變?yōu)榱私^對的0.


6 代碼結(jié)構(gòu)與注釋

6.1 結(jié)構(gòu)

71. 最小間隔應(yīng)該為2

for (i = 0; i < nElements; i++)

a[i] = 0;

間隔為1很難表述出代碼的邏輯性爸邢,超過4的間隔又使得代碼難以閱讀并且大大增加了分行的可能能啄寡。2和4比3更通用一些土全。加上減少分行的可能行报嵌,我們選擇了2作為間隔旷祸。


72. 代碼塊應(yīng)該像1(推薦)、2 的結(jié)構(gòu)一樣汹族,但絕對不要使用3中的樣式萧求。函數(shù)和類必須使用2 的結(jié)構(gòu)。

while (!done) {

???? doSomething();

???? done = moreToDo();

}

while (!done)

{

?? ?doSomething();

??? done = moreToDo();

}

while (!done)

? {

??? ?doSomething();

? ?? done = moreToDo();

? }

比較起1和2,3在不需要額外的縮進等級也進行了縮進顶瞒,使得代碼結(jié)構(gòu)不清晰夸政。


73. 類的定義應(yīng)當具有如下格式:

class SomeClass : public BaseClass

{

? public:

???? ...


? protected:

??? ?...


??private:

??? ...

}

這是上面一些規(guī)則的組合


74. 方法的定義應(yīng)當按照如下方式:

void someMethod()

{

? ...

}

這是上面一些規(guī)則的組合


75. if-else結(jié)構(gòu)應(yīng)當按照如下方式:

if (condition) {

? statements;

}


if (condition) {

? statements;

}

else {

? statements;

}


if (condition) {

? statements;

}

else if (condition) {

? statements;

}

else {

? statements;

}

這是上面一些規(guī)則的組合,有一些爭議是關(guān)于else是否要與if語句的尾括號在同一行

? if (condition) {

? ? statements;

? } else {

? ? statements;

? }

我們選擇了另起一行榴徐,這樣在遇到例如需要移動else語句塊時的情況可以方便一些守问。


76. 一個for語句應(yīng)當使用如下格式:

for (initialization; condition; update) {

?statements;

}

這是上面一些規(guī)則的組合

77. 一個空循環(huán)應(yīng)當使用如下格式:

for (initialization; condition; update)

?;

這強調(diào)了for的語句為空,讓讀者可以清晰的知道而不是忽略掉這個事實坑资。不過耗帕,空循環(huán)應(yīng)當被避免。


78. 一個while語句應(yīng)當使用如下格式:

while (condition) {

??statements;

}

這是上面一些規(guī)則的組合


79. 一個do-while循環(huán)應(yīng)當使用如下格式:

do {

? statements;

} while (condition);

這是上面一些規(guī)則的組合


80. 一個switch語句應(yīng)當使用如下格式:

switch (condition) {

? case ABC :

   statements;

   ?// Fallthrough


? case DEF :

statements;

break;


? case XYZ :

   statements;

??????? break;


? default :

   statements;

??????? break;

}

注意每個關(guān)鍵詞case在switch語句中都進行了對齊袱贮,這使得整個語句很清晰仿便。同樣要注意到在字符:處需要隔開。只要當一個case語句沒有break時攒巍,都應(yīng)當加上fallthrought的注釋嗽仪,來清晰的表明這里不需要break。


81. 一個try-catch語句應(yīng)當按照如下格式:

try {

? statements;

}

catch (Exception& exception) {

? statements;

}

這是上面一些規(guī)則的組合柒莉,而且關(guān)于if-else的討論在這里同樣適用闻坚。


82. 只有一句的if-else、for或while語句可以不使用括號常柄。

if (condition)

??statement;

while (condition)

? statement;

for (initialization; condition; update)

? statement;

通常的說,括號在這些語句中都應(yīng)該使用的搀擂。但括號是用來組織一段代碼的西潘,在單一行的代碼中使用顯得多余,不過有一種反對的觀點認為當增加語句時哨颂,會忘記增加括號喷市。但是不論怎樣,代碼不應(yīng)該是為了可能出現(xiàn)的變化來寫的威恼。( In general however, code should never be written to? for changes thatmightarise. )


83. 函數(shù)的返回值可以放在函數(shù)名的正上方品姓。

void

MyClass::myMethod(void)

{

    :

?}

在文件中,函數(shù)名在第一列更好認一些箫措。

6.2 空格

84.

- 普通的符號前后都使用1個空格的間隔腹备。

- C++ 關(guān)鍵詞后面使用1個空格的間隔。

- 逗號應(yīng)當在后面有1個空格的間隔斤蔓。

- 冒號前后都使用空格植酥。

- 語句中的分號后面應(yīng)該有1個空格。

a = (b + c) * d;// NOT: a=(b+c)*d

while (true)// NOT: while(true)

{

? ...

doSomething(a, b, c, d);// NOT: doSomething(a,b,c,d);


case 100 :// NOT: case 100:

for (i = 0; i < 10; i++) {// NOT: for(i=0;i<10;i++){

...

讓語句中的每一部分獨立出來,增加可讀性友驮,很難給出一份完整的清單漂羊,就通過例子給出了一些使用空格的方法吧。


85. 方法名的后面還有單詞時可以跟1個空格

doSomething (currentFile);

讓每個名字都清晰的表現(xiàn)出來卸留,增加可讀性走越。沒有后面的跟隨單詞,就可以忽略啦(doSomething())

另一種變化的方法是在括號處進行分離:doSomething( currentFile );雖然這種方法確實也讓每個名字都可以清晰的讀出來耻瑟,不過看上去不太自然旨指,而且如果省掉一個空格,那么看起來非常不對稱匆赃。


86. 在一個代碼段中邏輯上區(qū)分的單元應(yīng)該使用1個空行隔開淤毛。

Matrix4x4 matrix = new Matrix4x4();


double cosAngle = Math.cos(angle);

double sinAngle = Math.sin(angle);


matrix.setElement(1, 1, cosAngle);

matrix.setElement(1, 2, sinAngle);

matrix.setElement(2, 1, -sinAngle);

matrix.setElement(2, 2, cosAngle);


multiply(matrix);

使用空行增加邏輯上的可讀性。


87. 方法之間應(yīng)該使用三個空行隔開算柳。


使用更多的空間隔開方法低淡,可以讓類中方法清晰可見。


88. 聲明變量時應(yīng)該左對齊瞬项。

AsciiFile* file;

int    nPoints;

float   x, y;

增加可讀性蔗蹋,通過對齊可以清楚的看到變量的類型。


89. 當使用對齊可以增加可讀性的時候囱淋,果斷使用猪杭。

if??????? (a == lowValue)?????? compueSomething();

else if (a == mediumValue) computeSomethingElse();

else if (a == highValue)???? ?computeSomethingElseYet();


value = (potential     * oilDensity)???? / constant1 +

???????????(depth     ???? * waterDensity) / constant2 +

?????????? (zCoordinateValue * gasDensity)?? / constant3;


minPosition?????? = computeDistance(min, ? x, y, z);

averagePosition = computeDistance(average, x, y, z);


switch (value) {

    case PHASE_OIL???? ?: strcpy(phase, "Oil");????? break;

    case PHASE_WATER : strcpy(phase, "Water"); break;

    case PHASE_GAS????? : strcpy(phase, "Gas");??? break;

}

即使違反了指導(dǎo)妥衣,代碼中有很多地方可以通過增加空格來提高代碼的可讀性皂吮。許多這種情況都是為了代碼對齊。很難給出特定的指導(dǎo)税手,不過通過查看上面這段實現(xiàn)蜂筹,相信可以得出通用的結(jié)論。

6.3 注釋

90. 炫耀技巧的代碼不需要注釋——需要重寫B埂艺挪!


通過選用名字和清晰的結(jié)構(gòu),讓代碼盡量的可以自我解釋兵扬,把注釋控制在最小的使用范圍中麻裳。


91. 所有的注釋應(yīng)該使用英文。


在國際化的編譯環(huán)境中器钟,英語是第一語言津坑。


92. 包括多行注釋在內(nèi),對于所有的注釋都使用//

// Comment spanning

// more than one line.

使用//確保多級注釋可以準確的注釋自己想要注釋的內(nèi)容傲霸。調(diào)試可以使用/* */

在//和注釋內(nèi)容之間應(yīng)該有一個空格国瓮,而且注釋應(yīng)當以大寫字母開頭,以句號結(jié)束。


93. 注釋應(yīng)當與代碼位置一致

while (true) {// NOT: while (true) {

// Do something// Do something

something();something();}}

這樣避免注釋打亂了代碼的邏輯結(jié)構(gòu)乃摹。


94. 類和方法的初始注釋應(yīng)當按照javadoc的格式禁漓。


對于C/C++來說,JAVA的的文檔要專業(yè)很多孵睬,得益于javadoc作為了開發(fā)核心的一個標準播歼,它可以幫助把注釋變?yōu)楦哔|(zhì)量的格式

這是C++中實現(xiàn)了類似功能的工具,使用了和javadoc一樣的格式掰读。

Doc++orDoxygen.


7 引用

[1] Code Complete, Steve McConnell - Microsoft Press

[2] Programming in C++, Rules and Recommendations, M Henricson, e. Nyquist,? Ellemtel (Swedish telecom)

http://www.doc.ic.ac.uk/lab/cplus/c%2b%2b.rules/

[3] Wildfire C++ Programming Style, Keith Gabryelski, Wildfire Communications Inc.

http://www.wildfire.com/~ag/Engineering/Development/C++Style/

[4] C++ Coding Standard, Todd Hoff

http://www.possibility.com/Cpp/CppCodingStandard.html

[5] Doxygen documentation system

http://www.stack.nl/~dimitri/doxygen/index.html

致謝

Thanks to Robert P.J. Day for valuable contributions.

^~同樣感謝下自己秘狞,哈哈哈

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蹈集,隨后出現(xiàn)的幾起案子烁试,更是在濱河造成了極大的恐慌,老刑警劉巖拢肆,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件减响,死亡現(xiàn)場離奇詭異,居然都是意外死亡郭怪,警方通過查閱死者的電腦和手機支示,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鄙才,“玉大人颂鸿,你說我怎么就攤上這事≡茆郑” “怎么了嘴纺?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浓冒。 經(jīng)常有香客問我栽渴,道長,這世上最難降的妖魔是什么裆蒸? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任熔萧,我火速辦了婚禮糖驴,結(jié)果婚禮上僚祷,老公的妹妹穿的比我還像新娘。我一直安慰自己贮缕,他們只是感情好辙谜,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著感昼,像睡著了一般装哆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天蜕琴,我揣著相機與錄音萍桌,去河邊找鬼。 笑死凌简,一個胖子當著我的面吹牛上炎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雏搂,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼藕施,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了凸郑?” 一聲冷哼從身側(cè)響起裳食,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芙沥,沒想到半個月后诲祸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡憨愉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年烦绳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片配紫。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡径密,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躺孝,到底是詐尸還是另有隱情享扔,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布植袍,位于F島的核電站惧眠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏于个。R本人自食惡果不足惜氛魁,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厅篓。 院中可真熱鬧秀存,春花似錦、人聲如沸羽氮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽档押。三九已至澳盐,卻和暖如春祈纯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背叼耙。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工腕窥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人筛婉。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓油昂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親倾贰。 傳聞我的和親對象是個殘疾皇子冕碟,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容