本文为 ID: 萌面大道 http://maimieng.com/ 翻译,授权网易云课堂 C++ 程序设计入门(上)的崔毅东老师作为课件使用,大家可以免费下载,禁止用于商业用途,如需转载,需联系本人并保留此版权声明。(CC 版权声明在文末)
祝大家学有所成!
——Powered by 萌面大道
1 介绍
这份文档列出了 C++ 开发社区中 C++ 代码编写的基本指南。
这些建议是基于多个来源,个人经验,实际需求及一些给定的建议[1]-[4]收集来的而确定的标准。
引入一份新的指南而不只是引用以上的资料原因有很多。最主要是因为那些资料范围太过宽泛,并且更多的具体规则(尤其是命名规范)需要建立。同时,这份指南拥有注释,可以让它比大多数现存指南更简单地使用于检查项目中的代码。此外,编程指导通常以莫名其妙的方式和编程语言的技术问题混在一起。不过虽然这份文档不包含任何 C++ 技术建议,但聚焦于主要的编程风格。其他可以参考 C++ 编程实践指南。
集成开发环境(IDE)能够通过可视化接口,高亮代码,自动补全等提高代码可读性。程序员应该拒绝依赖这些特性。源代码应该被我们更多地注意而不是 IDE 对于代码的照顾,并且应当使代码独立于任何 IDE 但获得最大化的可读性。
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) {
...
}
1 介绍
这份文档列出了 C++ 开发社区中 C++ 代码编写的基本指南。
这些建议是基于多个来源,个人经验,实际需求及一些给定的建议[1]-[4]收集来的而确定的标准。
引入一份新的指南而不只是引用以上的资料原因有很多。最主要是因为那些资料范围太过宽泛,并且更多的具体规则(尤其是命名规范)需要建立。同时,这份指南拥有注释,可以让它比大多数现存指南更简单地使用于检查项目中的代码。此外,编程指导通常以莫名其妙的方式和编程语言的技术问题混在一起。不过虽然这份文档不包含任何 C++ 技术建议,但聚焦于主要的编程风格。其他可以参考 C++ 编程实践指南。
集成开发环境(IDE)能够通过可视化接口,高亮代码,自动补全等提高代码可读性。程序员应该拒绝依赖这些特性。源代码应该被我们更多地注意而不是 IDE 对于代码的照顾,并且应当使代码独立于任何 IDE 但获得最大化的可读性。
1.1 指南布局
这些指南以不同主题分组,并且每个建议都被标明序号,在审查代码时可以更方便地参考。 (译者注:最后一条是 94,不过在这其中有几条并不存在,源网站也没有。)
以下是指南的布局:
第三行很重要。代码标准和指南有可能引发争论,因此为它们标注来源是很重要的。
1.2 指南的重要性
在指南部分里,“必须”,“推荐”,“建议”均有特殊含义。“必须”是一定要遵守的,“推荐”是强烈建议,“建议”是一般指引。(译者注:为了标明此,有些语言进行了重组。)
2 通用指南
3 命名规范
3.1 一般命名规定
Line, SavingsAccount
line, savingsAccount
Line line;
。MAX_ITERATIONS, COLOR_RED, PI
getName(), computeTotalWidth()
model::analyzer, io::iomanager, common::math::geometry
dVD, hTML
等如此命名的变量可读性显然不高。另外还有一个问题在上述例子中已经说明;当名称和另外一个有联系,代码可读性会严重下降;缩略词并不那么像它本身那样独特。::
操作符。::mainWindow.open(), ::applicationContext.getName()
fileName; // NOT: filNavn
i, j, k, m, n
,字符型:c, d
。line.getLength(); // NOT: line.getLineLength();
3.2 特定命名规定
get/set
必须使用在直接存取属性的地方。compute
建议使用在需要计算的方法(函数)中。valueSet->computeAverage();
matrix->computeInverse();
find
建议使用在需要查找的方法(函数)中。vertex.findNearestVertex();
matrix.findMinElement();
initialize
建议使用在建立对象或概念。printer.initializeFontSet();
initialize
优于英式initialise
。最好避免使用缩略词init
。GUI
(图形化)组件的变量推荐使用组件类型作为后缀。mainWindow, propertiesDialog, widthScale, loginText,leftScrollbar, mainForm, fileMenu, minLabel, exitButton, yesToggle etc.
vector<Point> points;
int values[];
n
。nPoints, nLines
No
。tableNo, employeeNo
i
:iTable, iEmployee
。 这可以有效的命名迭代程序。i,j,k
等。j,k
等,推荐只在嵌套的循环中使用。is
。isSet, isVisible, isFinished, isFound, isOpen
status, flag
。而isStatus
或isFlag
又不太合适,因此程序员将被迫选择更多有含义的名字。has, can
和should
前缀:computeAverage(); // NOT: compAvg();
cmd
代替command
cp
代替copy
pt
代替point
comp
代替compute
init
代替initialize
HypertextMarkupLanguage
代替html
CentralProcessingUnit
代替cpu
PriceEarningRatio
代替pe
bool isError; // NOT: isNoError
bool isFound; // NOT: isNotFound
!isNotFound
直接看出其含义。Color::RED, Airline::AIR_FRANCE
等。Color {...}
。一个复数的名称像Colors {...}
,在声明时并没有什么区别,但这样的用法看起来比较笨拙。Exception
。void
型方法)。4 文件
4.1 源文件
.h
(推荐)或.hpp
作为扩展名。源文件应该为.c++
(推荐),.c
,.cc
或.cpp
。MyClass.c++, MyClass.h
MyClass.h, MyClass.c++
.h
文件内。4.2 包含文件和包含语句
Include
语句推荐将其按分类排级,并按等级从低到高排序。在两个Include
语句类之间空行分隔。Include
文件目录不能使用绝对路径。编译器指令应改为用于为包含的文件指示根目录。include
语句产生编译错误。5 语句
5.1 类型
public
部分放在最上,所以当人们可以看到protected/private
部分即可不再阅读。floatValue = static_cast<float>(intValue); // NOT: floatValue = intValue;
5.2 变量
int x, y, z;
getCenter(&x, &y, &z);
public
中声明。float* x; // NOT: float *x;
int& y; // NOT: int &y ;
0
不推荐用于布尔变量和指针。if (nLines != 0) // NOT: if (nLines)
if (value != 0.0) // NOT: if (value)
int
和float
型的0
和二进制0
行为相同。此外,使用明确的测试语句可以使被测试的类型更清晰。建议指针同样不应用0
隐式测试也很普遍,即if (line == 0)
代替if (line)
。后者在 C/C++ 看起来很普遍也可以使用。for()
语句内必须只能可包含循环控制语句。sum = 0; // NOT: for (i = 0, sum = 0; i < 100; i++)
for (i = 0; i < 100; i++) sum += value[i];
sum += value[i];
do-while
建议不使用。do-while
循环比普通的while
循环可读性差,因为其循环控制条件在底部。阅读代码者必须完全看完循环才能明确循环的范围。do-while
循环非必要。任何do-while
循环都可以重写为while
或for
循环。减少这种结构的使用来提高代码可读性。break
和continue
建议避免使用。while(true)
这种形式推荐用于无限循环中。for (;;)
可读性极差,并且表面上看不出它实际是个无限循环。5.4 条件语句
if
语句中,象征性的部分推荐放在if()
部分,例外放在else()
部分。if (isDone) // NOT: if (isDone) doCleanup();
doCleanup();
5.5 杂项
double total = 0.5; // NOT: double total = .5;
0.5
的可读性明显大于.5
;也不会使其和5
混淆。| 如果没有明确列出,C++ 将会默认返回值为
int
型。程序员不得依赖这个特点,因为这会使其他程序员觉得这种形式难以理解。goto
语句推荐尽量避免使用。goto
语句打破了代码的结构。只有在非常少的情况下(例如跳出一个深层的嵌套结构)goto
语句建议考虑,并且仅当替代的选择结构被证明有较差的可读性。0
推荐用来代替NULL
。NULL
是标准 C 语言库的部分,但在 C++ 中已被淘汰。6.1 布局
| 缩进 1 对于强调代码的逻辑布局显得太短。 | 缩进大于 4 使得深层的嵌套代码很难阅读,并且增加了必须分行的可能。选择缩进 2, 3, 4 之一,2 和 4 更加普遍,且选择 2 可以降低代码分行的可能。
if-else
语句推荐使用以下格式:else
从句和紧邻的if
或else
从句的括号在一行也是可行的,即:if-else
语句每个部分单独一行是更好的选择。这将使得语句控制变得更加简单,例如当需要移动else
部分时。for
语句推荐使用以下格式:| 这遵守了以上通用的代码块规则。
for
语句推荐使用以下格式:for
语句是空的,并且由于这是故意的所以使得代码阅读者清楚。不过,空循环应当避免。while
语句推荐使用以下格式:do-while
语句推荐使用以下格式:switch
语句推荐使用以下格式:| 注意整个
switch
语句中每个case
关键字相对缩进。这使得整个switch
语句清晰突出。此外注意“:”前的额外的空格。当case
语句不包含break
语句应当有明确的贯穿注释。省略break
是个普通错误,如果故意省略必须要让代码清晰。try-catch
语句推荐使用以下格式:| 这一定程度上遵守了以上通用的代码块规则。
if-else
语句关于大括号的规则通样可以运用于try-catch
语句。if-else, for
或while
语句建议不加大括号。6.2 空白
for
循环语句内的分号后推荐加空格以间隔。doSomething (currentFile);
doSomething()
),这种情况名称就不用独立。左圆括号后是否加空格这个规范并没有要求,即都是可以的。这个规范通常在右括号前留一个空格:doSomething( currentFile );
这样做使得每个名称作为不同含义而独立,但是右括号前的空格更像是一种艺术,并且没有那个空格的语句会显得不对称(doSomething( currentFile);)
。AsciiFile* file;
int nPoints;
float x, y;
6.3 注释
//
,包括多行注释。// Comment spanning
// more than one line.
//
注释确保注释所有文件部分总是可能的。调试等目的时使用/**/
。//
之间保留一个空格,并且注释应当以一个大写字母开头,以句号结束。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.htm
[5] Doxygen documentation system http://www.stack.nl/~dimitri/doxygen/index.html
[Translate]C++编程代码风格指南 由 萌面大道 创作,采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。
基于http://geosoft.no/development/cppstyle.html上的作品创作。
本许可协议授权之外的使用权限可以从 http://maimieng.com/ 处获得。