美文网首页我爱编程
C++编程风格指南-中文版

C++编程风格指南-中文版

作者: 我是阿喵酱 | 来源:发表于2016-10-12 21:45 被阅读0次

前⾔:
本⽂翻译⾃C++ Programming Style Guidelines原⽂地址
参考资料:Google机翻
本⽂仅供参考,如有错误希望指出。如有侵权,会⽴即删除,决不⽤于商业⽤途。
本⽂为ID: 萌⾯⼤道 http://maimieng.com/ 翻译,授权⺴易云课堂C++程序设计⼊⻔(上)的崔毅东⽼师作
为课件使⽤,⼤家可以免费下载,禁⽌⽤于商业⽤途,如需转载,需联系本⼈并保留此版权声明。(CC
版权声明在⽂末)
祝⼤家学有所成!
——by 萌⾯⼤道

1 介绍
这份⽂档列出了C++开发社区中C++代码编写的基本指南。
这些建议是基于多个来源,个⼈经验,实际需求及⼀些给定的建议[1]-[4]收集来的⽽确定的标准。
引⼊⼀份新的指南⽽不只是引⽤以上的资料原因有很多。最主要是因为那些资料范围太过宽泛,并且更多的
具体规则(尤其是命名规范)需要建⽴。同时,这份指南拥有注释,可以让它⽐⼤多数现存指南更简单地使
⽤于检查项⺫中的代码。此外,编程指导通常以莫名其妙的⽅式和编程语⾔的技术问题混在⼀起。不过虽然
这份⽂档不包含任何C++技术建议,但聚焦于主要的编程⻛格。其他可以参考C++编程实践指南。
集成开发环境(IDE)能够通过可视化接⼝,⾼亮代码,⾃动补全等提⾼代码可读性。程序员应该拒绝依赖
这些特性。源代码应该被我们更多地注意⽽不是IDE对于代码的照顾,并且应当使代码独⽴于任何IDE但获得
最⼤化的可读性。
1.1 指南布局
这些指南以不同主题分组,并且每个建议都被标明序号,在审查代码时可以更⽅便地参考。 (译者注:最后
⼀条是第94,不过在这其中有⼏条并不存在,源⺴站也没有。)
以下是指南的布局:

n. 指南简述
恰当的例⼦(以下此处不译)
原因, 来源 和 附加信息。

第三⾏很重要。代码标准和指南有可能引发争论,因此为它们标注来源是很重要的。
1.2 指南的重要性
在指南部分⾥,“必须”,“推荐”,“建议”均有特殊含义。“必须”是⼀定要遵守的,“推荐”是强烈建议,“建议”是
⼀般指引。(译者注:为了标明此,有些语⾔进⾏了重组。)
2 通⽤指南

  1. 任何违反此指南但提⾼代码可读性都是允许的。
    该指南的主要⺫的是提⾼代码可读性,从⽽使得⼀般数量级的代码更好的理解和维护。此指南不可能涵
    盖所有的特殊情况,这需要程序员的随机应变、灵活运⽤。
  2. 如果您和它持强烈不同的意⻅,您完全不必遵守此指南。
    制作这份指南,并不是⽤⼀个特定的代码⻛格去强加于每个⼈。有经验的程序员虽然通常采⽤类似这种
    规范,但有⼀份这样的指南,且让每个⼈都去熟悉它,通常可以使⼈们开始思考代码⻛格并评判在这个
    领域他们⾃⼰的习惯。
    另⼀⽅⾯,没有经验的程序员或者编程新⼿想要进⼊这⼀⾏当,通常遵循⼀个代码⻛格指南会让这段路
    途⾛得更加惬意。
    3 命名规范
    3.1 ⼀般命名规定
  3. 变量和常量类型的命名每个单词的⾸字⺟必须⼤写。
    Line, SavingsAccount
    C++开发社区惯例。
  4. 变量的命名⾸字⺟必须⼩写(其他单词⾸字⺟⼤写)。
    line, savingsAccount
    C++开发社区惯例。使得变量便于区别于类型,并且有效地解决了命名冲突,类似:Line line;。
  5. 常量的命名(包括枚举值)必须⽤下划线分隔单词并全部⼤写。
    MAXITERATIONS, COLORRED, PI
    C++开发社区惯例。通常,常量应尽量避免使⽤。⼤多数情况下,作为函数执⾏所得值是更好的选择:
    int getMaxIterations() // NOT: MAX_ITERATIONS = 25
    {
    return 25;
    }
    这种形式既能增加代码可读性,⼜能确保了对于类的值具有统⼀的接⼝。
  6. 函数或⽅法的命名必须是动词词组且⾸字⺟⼩写(其他单词⾸字⺟⼤写)。
    getName(), computeTotalWidth()
    C++开发社区惯例。此命名规范类似于变量的命名,但C++函数通过不同形式区别于变量名。
  7. 命名空间推荐以全部⼩写命名。
    model::analyzer, io::iomanager, common::math::geometry
    C++开发社区惯例。
  8. 命名模版类型推荐使⽤单⼀的⼤写字⺟。
    template ...
    template ...
    C++开发社区惯例。这使得模版名称突出于所有其他名称。
  9. 作为名称使⽤时,缩略词不得使⽤全部⼤写[4]。
    exportHtmlSource(); // NOT: exportHTMLSource();
    openDvdPlayer(); // NOT: openDVDPlayer();
    使⽤全部⼤写命名基本名称将会和上述的命名规范冲突。像dVD,hTML等如此命名的变量可读性显然不
    ⾼。另外还有⼀个问题在上述例⼦中已经说明;当名称和另外⼀个有联系,代码可读性会严重下降;缩
    略词并不那么像它本⾝那样独特。
  10. 全局变量推荐使⽤::操作符。
    ::mainWindow.open(), ::applicationContext.getName()
    通常,应避免使⽤全局变量。可以考虑使⽤单件模式对象来代替。
  11. 类的私有变量命名推荐以下划线为结尾。
    class SomeClass {
    private:
    int length_ ;
    }
    除了变量的名称和类型,作⽤域是其最重要的特性。使⽤下划线指⽰类的作⽤域可以很简单的区分局部
    变量和类的成员变量。这点很重要,因为类的成员变量⽐函数变量具有更⼤的作⽤域,因此更值得被程
    序员注意。此⽅法的另⼀个作⽤就是它很好的解决了为了给函数或构造器设值寻找合理的变量名:
    void setDepth (int depth)
    {
    depth_ = depth;
    }
    有⼀个问题就是使⽤前缀还是后缀下划线。两者都被⼲泛的使⽤,但是更加建议使⽤后缀,因为这样可
    以维持更好的可读性。
    需要注意的是,变量作⽤域的争议问题已经持续很久了,虽然好像现在这个指南已经获得了赞同,并且
    这将作为⼀条惯例在专业的开发者社区变得越来越普遍。
  12. 通⽤的变量推荐和其类型⼀致。
    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)
    通过减少术语和名称来减少代码复杂程度。此外,使得仅给出名字推断出类型变得容易。如果有⼀些原
    因似乎不能强烈地指出其类型名,就说明这是⼀种错误的选择。⾮通⽤的变量有⼀个特殊的⾓⾊。这些
    变量可以经常结合类型命名:
    Point startingPoint, centerPoint;
    Name loginName;
  13. 所有名称推荐使⽤英⽂。
    fileName; // NOT: filNavn
    在国际化开发中,英⽂是⾸选语⾔。
  14. 变量作⽤域越⻓,推荐使⽤更⻓的名称,作⽤域越短,建议使⽤较短的名称[1]。
    暂时存储或索引的临时变量名字最好较短。程序员阅读这些变量应该能推断出它的值不会在⼏⾏代码之
    外使⽤。常⻅的整型临时变量有:i, j, k, m, n,字符型:c, d。
  15. 对象的名字是暗⽰的且要避免出现在函数名称中。
    line.getLength(); // NOT: line.getLineLength();
    后者在类的声明中看起来很⾃然,但被在例⼦中被证明在使⽤中这是多余的。
    3.2 特定命名规定
  16. 术语get/set必须使⽤在直接存取属性的地⽅。
    employee.getName();
    employee.setName(name);
    matrix.getElement(2, 4);
    matrix.setElement(2, 4, value);
    C++开发社区惯例。在Java语⾔中,这个规定⼏乎已成为⼀种标准。
  17. 术语compute建议使⽤在需要计算的⽅法(函数)中。
    valueSet->computeAverage();
    matrix->computeInverse()
    给阅读代码者直接线索,这可能会是⼀个潜在的超时操作,若重复使⽤时,可能要考虑缓存的结果。⼀
    致的使⽤此规范可以增加代码可读性。
  18. 术语find建议使⽤在需要查找的⽅法(函数)中。
    vertex.findNearestVertex();
    matrix.findMinElement();
    给阅读代码者直接线索,这会是⼀个查找的⽅法(函数),只涉及简单的操作。⼀致的使⽤此规范可以
    增加代码可读性。
  19. 术语initialize建议使⽤在建⽴对象或概念。
    printer.initializeFontSet();
    美式initialize优于英式initialise。最好避免使⽤缩略词init。
  20. 代表GUI(图形化)组件的变量推荐使⽤组件类型作为后缀。
    mainWindow, propertiesDialog, widthScale, loginText,leftScrollbar, mainForm, fileMenu, minLabel,
    exitButton, yesToggle etc.
    从名称给出变量类型和对象资源的线索,可以提⾼代码可读性。
  21. 复数形式在表⽰对象集合时推荐使⽤。
    vector points;
    int values[];
    从名称给出变量类型和其中元素要进⾏的操作的线索,可以提⾼代码可读性。
  22. 若存在多个对象推荐加上前缀n。
    nPoints, nLines
    这种标号⽅式来⾃于数学,是⼀种已建⽴为标明多个对象的惯例。
  23. 独⽴的(实体)序号推荐加上后缀No。
    tableNo, employeeNo
    这种标号⽅式来⾃于数学,⼀种已建⽴为标明独⽴的(实体)序号的惯例。
    ⼀种更为优雅的⽅式是使⽤前缀i:iTable, iEmployee. 这可以有效的命名迭代程序。
  24. 迭代程序(器)推荐命名为i,j,k等。
    for (int i = 0; i < nTables); i++) {
    :
    }
    for (vector::iterator i = list.begin(); i != list.end(); i++) {
    Element element = *i;
    ...
    }
    这种标号⽅式来⾃于数学,⼀种已建⽴为标明迭代程序(器)的惯例。
    变量名j,k等,推荐只在嵌套的循环中使⽤。
  25. 布尔变量和⽅法(函数)推荐加上前缀is。
    isSet, isVisible, isFinished, isFound, isOpen
    C++开发社区和Java部分强制惯例。
    使⽤后缀解决了⼀个常⻅的问题,即选择不好的布尔变量名称,类似:status,flag。⽽isStatus或isFlag
    ⼜不太合适,因此程序员将被迫选择更多有含义的名字。
    这⾥有⼀些在某些条件下更好的前缀⽅案供选择,他们是has,can和should前缀:
    bool hasLicense();
    bool canEvaluate();
    bool shouldSort();
  26. 互补的名称必须⽤在互补的操作[1]。
    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, etc.
    通过对称性减少代码复杂程度
  27. 名称中最好避免出现缩略词。
    computeAverage(); // NOT: compAvg();
    有两种类型的单词需要注意。第⼀种是词典中列出的普通词,这些不得简写,千万不要这样写:
    cmd 代替 command
    cp 代替 copy
    pt 代替 point
    comp 代替 compute
    init 代替 initialize

    另⼀种是具有特殊含义的词组,通过他们的缩略词可以更⾃然的为⼈们所知,这些词组要保持缩略形
    式,千万不要这样写:
    HypertextMarkupLanguage 代替 html
    CentralProcessingUnit 代替 cpu
    PriceEarningRatio 代替 pe
  28. 最好避免特殊地命名指针。
    Line* line; // NOT: Line* pLine;
    // NOT: LIne* linePtr;
    C/C++环境有许多指针类型的变量,所以很多规定⼏乎⽆法遵守。此外,程序员应当忽略C++的对象通
    常斜体的特殊惯例。只有当对象的实际类型具有特殊意义,名称才应强调类型。
  29. 最好避免出现否定的布尔变量名。
    bool isError; // NOT: isNoError
    bool isFound; // NOT: isNotFound
    当⼀个名称出现双重否定时,会出现问题。因为不能从!isNotFound直接看出其含义。
  30. 枚举常量建议以共同的类型名作为前缀。
    enum Color {
    COLOR_RED,
    COLOR_GREEN,
    COLOR_BLUE
    };
    在声明处给出额外的信息,可以看出哪些常量是共通的,以及这些常量所代表的意义。⼀种代替⽅案是
    总是通过共同的类型名联系这些常量:Color::RED, Airline::AIR_FRANCE等。
    注意,枚举名应当是典型的单数Color {...}。⼀个复数的名称像Colors {...},在声明时并没有什么区别,
    但这样的⽤法看起来⽐较笨拙。
  31. 例外的类推荐加上后缀Exception。
    class AccessException
    {
    :
    }
    例外的类其实不是程序主要设计的⼀部分,通过命名让它们相对于其他类更加突出。
  32. 函数(具有返回值的⽅法)推荐命名为它们执⾏后的返回或者规程(void型⽅法)。
    增加代码可读性。使得可以很清晰的看出其功能,尤其是其不⽀持什么功能。这将再⼀次使代码简化避
    免副作⽤的产⽣。
    4 ⽂件
    4.1 源⽂件
  33. C++头⽂件推荐以.h(推荐)或.hpp作为扩展名。源⽂件应该为.c++(推荐),.c,.cc或.cpp。
    MyClass.c++, MyClass.h
    以上均为C++标准⽀持的⽂件后缀名。
  34. 类推荐在头⽂件中声明,并在类名和⽂件名匹配的源⽂件中定义。
    MyClass.h, MyClass.c++
    易于找到给定类的相关⽂件。⼀个明显的例外,即模版类声明和定义必须在同⼀个.h⽂件内。
  35. 推荐把所有的定义包含在源⽂件中。
    class MyClass
    {
    public:
    int getValue () {return value_ ;} // NO!
    ...
    private:
    int value_;
    }
    头⽂件应当声明⼀个接⼝,源⽂件应执⾏它。当寻找,执⾏时,程序员应总是清楚它可以在源⽂件中找
    到。
  36. ⽂件⺫录必须在80列内。
    80列是编辑器,终端,显⽰端和调试器中共同的宽度,并且⽂件将在很多⼈中共享,所以应当保持这些
    系统规定参数。在程序员之间传递代码时,避免⽆意义的断⾏,能够提升代码可读性。
  37. 分⻚符和Tab等特殊符号必须避免在程序中出现。
    这些字符⽤在多⼈编程,多平台时将必定导致编辑器,显⽰端,终端模拟器或者调试器出现问题。
  38. 分⾏显⽰的代码必须使其显⽽易⻅[1]。
    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列的极限时需要分⾏。很难给出严格的规定什么情况需要分⾏,但是上⾯的例⼦可以
    作为参考。通常:
    逗号后分⾏
    操作符后分⾏
    对准上⼀⾏的表达式的开始的新的⼀⾏
    4.2 包含⽂件和包含语句
  39. 头⽂件必须放在⼀个保护装置中。

ifndef COMCOMPANYMODULECLASSNAMEH

define COMCOMPANYMODULECLASSNAMEH

:

endif // COMCOMPANYMODULECLASSNAMEH

这个结构是为了避免产⽣编译错误。
这个命名规定统⼀了源代码中头⽂件的位置,避免了命名冲突。

  1. Include语句推荐将其按分类排级,并按等级从低到⾼排序。在两个Include语句类之间空⾏分隔。

include

include

include

include

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

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

除了展⽰给阅读代码者清晰的包含⽂件结构,同样可以直接看出涉及哪些模块。
Include⽂件⺫录不能使⽤绝对路径。编译器指令应改为⽤于为包含的⽂件指⽰根⺫录。

  1. include语句必须只放在⽂件顶端。
    通⽤规范。避免隐藏(在⽂件内)的include语句产⽣编译错误。
    5 语句
    5.1 类型
  2. 在⽂件内部使⽤的量的类型建议在此⽂件内声明。
    确保信息隐藏。
  3. 类的⼀部分必须分为公共,保护和私有三部分[2][3]。所有部分必须明确。不合适的部分不应
    混在⼀起。
    顺序通常为将public部分放在最上,所以当⼈们可以看到protected/private部分即可不再阅读。
  4. 类型转换必须明确作出。绝不能依赖隐性类型转换。
    floatValue = static_cast(intValue); // NOT: floatValue = intValue;
    通过这点,程序员可以意识到涉及到的不同类型,并且混合是有意的。
    5.2 变量
  5. 变量推荐在声明处初始化。
    这确保了变量在任何时候都是有效的。有时不能以⼀个有效值初始化变量,就像:
    int x, y, z;
    getCenter(&x, &y, &z);
    这些情况,应当保持未初始化,这要好于初始化假值。
  6. 变量绝不能拥有双重含义。
    通过确保变量唯⼀地代表概念来提升代码可读性。减少副作⽤导致错误的机会。
  7. 尽量避免使⽤全局变量。
    在C++中,全局变量并不是必需的。同样适⽤于全局函数或者⽂件范围的(静态)变量。
  8. 类中变量尽量不要在public中声明。
    公有变量将会破环C++的信息隐藏性和封装性。使⽤私有变量和访问函数代替。这种规则的⼀种例外是
    当类本质上是没有⾏为(类似C的结构体)的⼀种数据结构。这种情况下,让实例变量变公有是恰当的
    [2]。
    注意:C++的结构体只是为了和C语⾔的⼀致性,并通过减少构建结构体的数量避免增加代码可读性。使
    ⽤类来代替。
  9. C++的指针和引⽤的符号推荐靠近类型名,⽽不是靠近名称。
    float* x; // NOT: float *x;
    int& y; // NOT: int &y ;
    变量的指针或者引⽤属性是类型的性质,⽽不是命名的。C语⾔程序员经常在两者中取舍,⽽C++中遵守
    这个规则已越来越普遍。
  10. 隐式测试0不推荐⽤于布尔变量和指针。
    if (nLines != 0) // NOT: if (nLines)
    if (value != 0.0) // NOT: if (value)
    依据C++标准,没必要定义int和float型的0和⼆进制0⾏为相同。此外,使⽤明确的测试语句可以使被测
    试的类型更清晰。建议指针同样不应⽤0隐式测试也很普遍,即if (line == 0)代替if (line)。后者在
    C/C++看起来很普遍也可以使⽤。
  11. 推荐在尽可能⼩的范围内进⾏变量声明。
    在⼩范围保持变量的操作,这样可以更简单的控制其作⽤和副作⽤。
  12. for()语句内必须只能可包含循环控制语句。
    sum = 0; // NOT: for (i = 0, sum = 0; i < 100; i++)
    for (i = 0; i < 100; i++) sum += value[i];
    sum += value[i];
    增强代码的可维护性和可读性。使得控制体和循环包含更加清晰。
  13. 循环变量推荐在循环之前被初始化。
    isDone = false; // NOT: bool isDone = false;
    while (!isDone) { // :
    : // while (!isDone) {
    } // :
    // }
  14. do-while建议不使⽤。
    do-while循环⽐普通的while循环可读性差,因为其循环控制条件在底部。阅读代码者必须完全看完循
    环才能明确循环的范围。
    此外,do-while循环⾮必要。任何do-while循环都可以重写为while或for循环。减少这种结构的使⽤来
    提⾼代码可读性。
  15. 循环体的break和continue建议避免使⽤。
    如果这些语句相较于同样的结构化代码可以提⾼代码可读性,否则建议不使⽤。
  16. while(true)这种形式推荐⽤于⽆限循环中。
    while (true) {
    :
    }
    for (;;) { // NO!
    :
    }
    while (1) { // NO!
    :
    }
    依靠对于1进⾏的测试既没有必要也没有意义。for (;;)可读性极差,并且表⾯上看不出它实际是个⽆限循
    环。
    5.4 条件语句
  17. 复杂的条件表达式必须避免。引⼊临时布尔变量代替[1]。
    bool isFinished = (elementNo < 0)
    bool isRepeatedEntry = elementNo == lastElement;
    if (isFinished
    :
    }
    // NOT:
    if ((elementNo < 0)
    elementNo == lastElement) {
    :
    }
    通过给表达式分配布尔变量,程序可以⾃动记录(分析)。这样的结构造可以更简单的阅读,改正和维
    护。
  18. if语句中,象征性的部分推荐放在if()部分,例外放在else()部分。
    bool isOk = readFile (fileName);
    if (isOk) {
    :
    }
    else {
    :
    }
    确保例外不会使得正常路径难以理解。这对于代码的可读性和性能均很重要。
  19. 条件语句推荐放在单独的⼀⾏。
    if (isDone) // NOT: if (isDone) doCleanup();
    doCleanup();
    这是为了⽅便调试。当写在⼀⾏中,⽆法清晰的知道真或假。
  20. 条件语句中的执⾏语句必须避免。
    File* fileHandle = open(fileName, "w");
    if (!fileHandle) {
    :
    }
    // NOT:
    if (!(fileHandle = open(fileName, "w"))) {
    :
    }
    条件语句中的执⾏语句使得代码难以阅读。这需要C/C++的新程序员尤其注意。
    5.5 杂项
  21. 代码中推荐尽量避免幻数的使⽤。除了0和1,其他的推荐考虑声明常量代替。
    如果⼀个数字⾃⾝没有⼀个显⽽易⻅的含义,通过引⼊命名常量代替来增加代码可读性。另⼀种不同的
    ⽅法是在量被访问处引⼊⼀个⽅法(函数)。
  22. 浮点数推荐总是带有⼩数点和⾄少⼀位⼩数。
    double total = 0.0; // NOT: double total = 0;
    double speed = 3.0e8; // NOT: double speed = 3e8;
    double sum;
    :
    sum = (a + b) * 10.0;
    这强调了整型和浮点型不同的性质。这两种算数模型是完全不同且毫不相容的概念。
    同样,在上述最后⼀个例⼦中,他在某处强调了代码中变量(sum)分配的类型,虽然这可能看起来不
    太明显。
  23. ⼩于0的浮点数推荐总是在⼩数点前写上数码0。
    double total = 0.5; // NOT: double total = .5;
    C++的数字和表达式系统借鉴于数学,并且语法应当只要允许就遵守数学惯例。同样,0.5的可读性明显
    ⼤于.5;也不会使其和5混淆。
  24. 函数必须要明确列出返回值类型。
    int getValue() // NOT: getValue()
    {
    :
    }
    如果没有明确列出,C++将会默认返回值为int型。程序员不得依赖这个特点,因为这会使其他程序员觉
    得这种形式难以理解。
  25. goto语句推荐尽量避免使⽤。
    goto语句打破了代码的结构。只有在⾮常少的情况下(例如跳出⼀个深层的嵌套结构)goto语句建议考
    虑,并且仅当替代的选择结构被证明有较差的可读性。
  26. 0推荐⽤来代替NULL。
    NULL是标准C语⾔库的部分,但在C++中已被淘汰。
    6.1 布局
  27. 基本的缩进推荐为2个空格。
    for (i = 0; i < nElements; i++)
    a[i] = 0;
    缩进1对于强调代码的逻辑布局显得太短。
    缩进⼤于4使得深层的嵌套代码很难阅读,并且增加了必须分⾏的可能。选择缩进2,3,4之⼀,2和4更
    加普遍,且选择2可以降低代码分⾏的可能。
  28. 代码块的布局推荐如例1(推荐)或者例2,但绝不要如例3[4]。函数和类代码块必须使⽤例2的布
    局。
    while (!done) {
    doSomething();
    done = moreToDo();
    }
    while (!done)
    {
    doSomething();
    done = moreToDo();
    }
    while (!done)
    {
    doSomething();
    done = moreToDo();
    }
    例3引⼊⼀个特别的缩进,使得强调的代码逻辑结构不如例1和例2清晰。
  29. 类推荐使⽤以下格式声明:
    class SomeClass : public BaseClass
    {
    public:
    ...
    protected:
    ...
    private:
    ...
    }
    这⼀定程度上遵守了以上通⽤的代码块规则。
  30. ⽅法(函数)推荐使⽤以下格式定义:
    void someMethod()
    {
    ...
    }
    这遵守了以上通⽤的代码块规则。
  31. if-else语句推荐使⽤以下格式:
    if (condition) {
    statements;
    }
    if (condition) {
    statements;
    }
    else {
    statements;
    }
    if (condition) {
    statements;
    }
    else if (condition) {
    statements;
    }
    else {
    statements;
    }
    这⼀定程度上遵守了以上通⽤的代码块规则。但是,如果⼀个else从句和紧邻的if或else从句的括号在⼀
    ⾏也是可⾏的,即:
    if (condition) {
    statements;
    } else {
    statements;
    }
    代码中if-else语句每个部分单独⼀⾏是更好的选择。这将使得语句控制变得更加简单,例如当需要移动
    else部分时。
  32. for语句推荐使⽤以下格式:
    for (initialization; condition; update) {
    statements;
    }
    这遵守了以上通⽤的代码块规则。
  33. 空的for语句推荐使⽤以下格式:
    for (initialization; condition; update)
    ;
    这强调了for语句是空的,并且由于这是故意的所以使得代码阅读者清楚。不过,空循环应当避免。
  34. while语句推荐使⽤以下格式:
    while (condition) {
    statements;
    }
    这遵守了以上通⽤的代码块规则。
  35. do-while语句推荐使⽤以下格式:
    do {
    statements;
    } while (condition);
    这遵守了以上通⽤的代码块规则。
  36. switch语句推荐使⽤以下格式:
    switch (condition) {
    case ABC :
    statements;
    // Fallthrough
    case DEF :
    statements;
    break;
    case XYZ :
    statements;
    break;
    default :
    statements;
    break;
    }
    注意整个switch语句中每个case关键字相对缩进。这使得整个switch语句清晰突出。此外注意“:”前的额
    外的空格。当case语句不包含break语句应当有明确的贯穿注释。省略break是个普通错误,如果故意省
    略必须要让代码清晰。
  37. try-catch语句推荐使⽤以下格式:
    try {
    statements;
    }
    catch (Exception& exception) {
    statements;
    }
    这⼀定程度上遵守了以上通⽤的代码块规则。if-else语句关于⼤括号的规则通样可以运⽤于try-catch语
    句。
  38. 单独的if-else,for,或while语句建议不加⼤括号。
    if (condition)
    statement;
    while (condition)
    statement;
    for (initialization; condition; update)
    statement;
    通常推荐应当是在任何情况⼤括号都不应缺少。但是,通常语⾔构造中⼤括号是⽤来归纳多条语句。单
    条语句使⽤⼤括号会显得多余。不过,有⼀种反对此语法的声⾳,如果增加语句⽽忘记加⼤括号,代码
    就会出错。但不论怎样,代码绝不应当为了适应可能发⽣的改变。
  39. 函数的返回值类型建议放在函数名上⽅左对⻬。
    void
    MyClass::myMethod(void)
    {
    :
    }
    这使得更容易发现函数名,因为它们都在第⼀列开始。
    6.2 空⽩

-常规操作符推荐在前后加空格以间隔。
-C++保留字后推荐加空格以间隔。
-逗号后推荐加空格以间隔。
-冒号推荐在前后加空格以间隔
-for循环语句内的分号后推荐加空格以间隔。
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++){
...
让语句的每⼀部分都独⽴出来。增加代码可读性。在C++代码中,很难给出⼀个完整的空格使⽤建议列
表。以上的例⼦只是给出⼀个通常的建议。

  1. ⽅法(函数)名后若相连其他名称,建议以空格隔开。
    doSomething (currentFile);
    让每个名称独⽴出来。增加代码可读性。当后⾯没有名称,空格可以省略(doSomething()),这种情况名
    称就不⽤独⽴。左圆括号后是否加空格这个规范并没有要求,即都是可以的。这个规范通常在右括号前
    留⼀个空格: doSomething( currentFile ); 这样做使得每个名称作为不同含义⽽独⽴,但是右括号前的
    空格更像是⼀种艺术,并且没有那个空格的语句会显得不对称(doSomething( currentFile);)。
  2. 逻辑集合代码块推荐以空⾏分隔。
    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);
    通过在不同的逻辑集合代码块加⼊空⾏增加代码可读性。
  3. ⽅法(函数)推荐以三个空⾏分隔。
    通过⼤空⾏使得⽅法(函数)在类中独⽴。
  4. 变量声明建议左对⻬。
    AsciiFile* file;
    int nPoints;
    float x, y;
    增加代码可读性。变量可以通过对⻬简单的分别类型。
  5. 当使⽤对⻬可以增加代码可读性就使⽤对⻬。
    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;
    }
    尽管这点违反了普遍的规范,但是代码中很多地⽅需要如此来增加代码可读性就是允许的。上述很多情
    况下不得不要将代码对⻬。代码对⻬的通⽤规范很难给出,但是以上的例⼦就是很通⽤的线索。
    6.3 注释
  6. ⽆厘头的代码不需要注释,需要重写![1]。
    通常,注释应当通过代码命名的选择和明确的逻辑结构提升⾃⾝⽂档化⽽尽量减少使⽤。
  7. 所有注释推荐使⽤英⽂书写[2]。
    在国际化开发环境中,英⽂是⾸选语⾔。
  8. 所有注释均⽤//,包括多⾏注释。
    // Comment spanning
    // more than one line.
    ⾃从多级C注释不被⽀持,使⽤//注释确保注释所有⽂件部分总是可能的。调试等⺫的时使⽤/**/。
    推荐真正注释和//之间保留⼀个空格,并且注释应当以⼀个⼤写字⺟开头,以句号结束。
  9. 推荐将注释和代码同等位置(缩进)。
    while (true) { // NOT: while (true) {
    // Do something // Do something
    something(); something();
    } }
    这是为了避免注释打破程序的逻辑结构。
  10. 类和⽅法的初始注释推荐依照javaDoc规定。
    作为标准的类和⽅法⽂档,Java开发社区⽐C/C++开发社区要更加成熟。这是因为标准⾃动化Javadoc
    ⼯具是开发套件的⼀部分,并且它⽤这些注释帮助做出⾼质量超⽂本⽂档。类Javadoc⼯具同样可⽤于
    C++。这些相同的标签语法类似于Javadoc。看这⾥的Doc++或Doxygen实例。
    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/ 处获得。

相关文章

网友评论

    本文标题:C++编程风格指南-中文版

    本文链接:https://www.haomeiwen.com/subject/xsaiyttx.html