【代码规范】google开源c\c++项目代码规范

				版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载;https://blog.csdn.net/csdn_baotai					https://blog.csdn.net/csdn_baotai/article/details/80304636				</div>
							            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d7e2a68c7c.css">
					<div class="htmledit_views" id="content_views">
            <h1 style="margin-top:0px;background-color:rgb(242,242,242);"><a name="t0"></a><span style="font-family:'Microsoft YaHei';font-size:24px;color:#339999;"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">google开源</span></span></span></span><span style="vertical-align:inherit;"><span style="vertical-align:inherit;"> C / C ++项目代码规范</span></span></span></h1><h1 style="margin-top:0px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><a name="t1"></a><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">1.头文件</span></span></h1><p style="line-height:24px;margin-bottom:24px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">每通常一个&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件都有一个对应的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件。</span><span style="vertical-align:inherit;">也有一些常见例外,如单元测试代码和只包含&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">main()</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;函数的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">正确使用头文件可令代码在可读性,文件大小和性能上大为改观。</span></span></p><p style="line-height:24px;margin-bottom:24px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">下面的规则将引导你规避使用头文件时的各种陷阱。</span></span></p><div class="section" style="color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="font-family:'Microsoft YaHei';"><span></span></span><h2 style="margin-top:0px;"><a name="t2"></a><span style="font-family:'Microsoft YaHei';vertical-align:inherit;"><span style="vertical-align:inherit;">1.1。</span><span style="vertical-align:inherit;">自包含的头文件</span></span></h2><div class="admonition tip" style="padding:12px;line-height:24px;margin-bottom:24px;background:rgb(219,250,244);"><p class="first admonition-title" style="line-height:1;margin:-12px -12px 12px;font-weight:bold;color:rgb(255,255,255);background:rgb(26,188,156);padding:6px 12px;"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">TIP</span></span></p><p class="last" style="line-height:24px;margin-bottom:0px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">头文件应该能够自给自足(自包含的,也就是可以作为第一个头文件被引入</span><span style="vertical-align:inherit;">),以&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;结尾。至于用来插入文本的文件,说到底它们并不是头文件,所以以应&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.inc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;结尾不允许。出分离&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">-inl.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;头文件的做法。</span></span></span></p></div><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">所有头文件要能够自给自足。换言之,用户和重构工具不需要为特别场合而包含额外的头文件。详言之,一个头文件要有&nbsp; </span></span><a class="reference internal" href="http://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/headers/#define-guard" rel="nofollow" style="color:rgb(155,89,182);" target="_blank"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">1.2。</span><span style="vertical-align:inherit;">#define保护</span></span></a><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">,统计包含它所需要的其它头文件,也不要求定义任何特别的符号。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">不过有一个例外,即一个文件并不是自足的,而是作为文本插入到代码某处。或者,文件内容实际上是其它头文件的特定平台</span><span style="vertical-align:inherit;">(特定于平台)扩展部分,这些文件就要用&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.inc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件扩展名。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">如果&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件声明了一个模板或内联函数</span><span style="vertical-align:inherit;">,同时也在该文件加以定义。有用凡是到这些的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件,就得统统包含该头文件,否则程序可能会在构建中链接失败</span><span style="vertical-align:inherit;">。不要把这些定义放到分离的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">-inl.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件里(译者注:过去该规范曾提倡把定义放到-inl.h里过)。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">有个例外:如果某函数模板为所有相关模板参数显式实例化</span><span style="vertical-align:inherit;">,或本身就是某类的一个私有成员,它就那么定义只能在实例化该模板的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件里。</span></span></span></p></div><div class="section" style="color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="font-family:'Microsoft YaHei';"><span></span></span><h2 style="margin-top:0px;"><a name="t3"></a><span style="font-family:'Microsoft YaHei';vertical-align:inherit;"><span style="vertical-align:inherit;">1.2。</span><span style="vertical-align:inherit;">#define保护</span></span></h2><div class="admonition tip" style="padding:12px;line-height:24px;margin-bottom:24px;background:rgb(219,250,244);"><p class="first admonition-title" style="line-height:1;margin:-12px -12px 12px;font-weight:bold;color:rgb(255,255,255);background:rgb(26,188,156);padding:6px 12px;"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">TIP</span></span></p><p class="last" style="line-height:24px;margin-bottom:0px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">所有头文件都应该使用&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">#define</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;来防止头文件被多重包含,命名格式当是:&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">&lt;PROJECT&gt;_&lt;PATH&gt;_&lt;FILE&gt;_H_</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;。</span></span></span></p></div><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">为保证唯一性,头文件的命名应该基于所有项目源代码树的全路径。</span><span style="vertical-align:inherit;">例如,项目&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">foo</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;中的头文件&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">foo/src/bar/baz.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;可按如下方式保护:</span></span></span></p><div class="highlight-c++" style="border:1px solid rgb(225,228,229);padding:0px;margin:1px 0px 24px;"><div class="highlight" style="border:none;padding:0px;margin:0px;"><pre style="margin-bottom:0px;padding:12px;line-height:normal;"><span style="font-family:'Microsoft YaHei';"><span class="cp"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">#ifndef FOO_BAR_BAZ_H_ </span></span></span>

#define FOO_BAR_BAZ_H_

#endif // FOO_BAR_BAZ_H_

1.3。前置声明

TIP

尽可能地避免使用前置声明。使用  #include 所有游戏需要的头文件即可。

定义:

所谓「前置声明」(forward declaration)是类,函数和模板的纯粹声明,没伴随着其定义。

优点:

  • 前置声明能够节省编译时间,的多余  #include 会迫使compile-器展开更多的文件,处理更多的输入。
  • 前置声明能够节省不必要的重新编译的时间。  #include 使代码因为头文件中无关的改动而被重新编译多次。

缺点:

  • 前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过必要的重新编译过程。

  • 前置声明可能会被库的后续更改所破坏。前置声明函数或模板有时会妨碍头文件开发者变动其API。例如扩大形参类型,加个自带默认参数的模板形参等等。

  • 前置声明来自命名空间  std:: 的符号时,其行为未定义。

  • 很难判断什么时候该用前置声明,时候什么用该  #include 极端情况下,用前置声明代替。  includes 甚至都会暗暗地改变代码的含义:

    // bh:
    struct B {};
    struct D B {}

// good_user.cc:
包括 “BH”
void f B * );
void f void * );
void test D * x { f x ); } //调用f(B

如果  #include 被  B 状语从句:  D 的前置声明替代,  test() 就会调用  f(void) 。
  • 前置声明了include 不少来自头文件的符号时,就会比单单一行的  冗长。
  • 仅仅为了能前置声明而重构代码(比如用指针成员代替对象成员)会使代码变得更慢更复杂。

结论:

  • 尽量避免前置声明那些定义在其他项目中的实体。
  • 函数:总是使用  #include
  • 类模板:优先使用  #include

至于什么时候包含头文件,参见  1.5。#include的路径及顺序  。

1.4。内联函数

TIP

只有当函数只有10行甚至更少时才将其定义为内联函数。

定义:

当函数被声明为内联函数之后,编译器会将其内联展开,而不是按通常的函数调用机制进行调用。

优点:

只要内联的函数体小小,内联该函数可以令目标代码更加高效。对于存取函数以及其它函数体比较短,性​​能关键的函数,鼓励使用内联。

缺点:

滥用内联将导致程序变得更慢。内联可能使目标代码量或增或减,这取决于内联函数的大小。内联非常短小的存取函数通常会减少代码大小,但内联一个相当大的函数将戏剧性的增加代码大小。现代处理器由于更好的利用了指令缓存,小巧的代码往往执行更快。

结论:

一个较为合理的经验准则是,不要内联超过10行的函数。谨谨对待析构函数,析构函数往往比其表面看起来要更长,因为有隐含的成员和基类析构函数被调用!

另一个实用的经验准则:内联那些包含循环或  switch 语句的函数常常是得不偿失(除非在大多数情况下,这些循环或  switch 语句从不被执行)。

有些函数即使声明为内联的也不一定会被编译器内联,这点很重要; 比如虚函数和递归函数就不会被正常内联。通常,递归函数不应该声明成内联函数。(YuleFox注:递归调用堆栈的展开并不像循环那么简单,比如递进层数在编译时可能是未知的,大多数编译器都不支持内联递归函数)。虚函数内联的主要原因是想把它的函数体放在类定义内,为了图个方便,抑或是当作文件描述其行为,比如精短的存取函数。

1.5。  #include 的路径及顺序

TIP

使用标准的头文件包含顺序可增强可读性,避免隐藏依赖:相关头文件,C库,C ++库,其他库的  .h,本项目内的  .h

项目内部文件应按照项目源代码目录树结构排列,避免使用UNIX特殊的快捷目录  .(当前目录)或   (上级目录)。例如,  google-awesome-project/src/base/logging.h 应该按如下方式包含:

#include  “base / logging.h”

又如,  dir/foo.cc 或  dir/foo_test.cc 的主要作用英文的英文实现或测试  dir2/foo2.h 的功能,  foo.cc 中包含头文件的次序如下:

  1. dir2/foo2.h (优先位置,详情如下)
  2. C系统文件
  3. C ++系统文件
  4. 库其他的  .h 文件
  5. 项目本。内  .h 文件

优先这种顺序的排序保证当  dir2/foo2.h 遗漏某些必要的库时,  dir/foo.cc 或  dir/foo_test.cc 的构建会立刻中止。因此这一条规则保证维护这些文件的人们首先看到构建中止的消息而不是维护其他包的人们

dir/foo.cc 和  dir2/foo2.h 通常位于同一目录下(如  base/basictypes_unittest.cc 和  base/basictypes.h),但也可放在不同目录下。

按字母顺序分别对每种类型的头文件进行二次排序是不错的主意。注意较老的代码可不符合这条规则,要在方便的时候改正它们。

您所依赖的符号(符号)被哪些头文件所定义,您就应该包含(包括)哪些头文件,前置声明  (向前声明)情况除外。您比如要用到  bar.h 中的某个符号,哪怕您所包含的  foo.h 已经包含了  bar.h,也照样得包含  bar.h,除非foo.h 有明确  说明它会自动向您提供  bar.h 中符号。不过,凡是cc文件所对应的「相关头文件」已经包含的,就不用再重复包含进其cc文件里面了,就像  foo.cc 只包含  foo.h就够了,不用再管后者所包含的其它内容。

#include “foo / public / fooserver.h”//优先位置

#include “foo / public / bar.h”例如,   google-awesome-project/src/foo/internal/fooserver.cc 包含次序如下:

 
  

4.函数

4.1。参数顺序

总述

函数的参数顺序为:输入参数在先,后跟输出参数。

说明

C / C ++中的函数参数或者是函数的输入,或者是函数的输出,或兼而有之。输入参数通常是值参或  const 引用,输出参数或输入/输出参数则一般为非  const 指针。在排列参数顺序时,将所有的输入参数置于输出参数之前。特别要注意,在加入新参数时不要因为它们是新参数就置于参数列表最后,而是仍然要按照前述的规则,即将新的输入参数也置于输出参数之前。

这并非一个硬性规定。输入/输出参数(通常是类或结构体)让这个问题变得复杂。并且,有时候为了其他函数保持一致,你可能不得不不所有变通。

4.2。编写简短函数

总述

我们倾向于编写简短,凝练的函数。

说明

我们承认长函数有时是合理的,因此并不硬限制函数的长度。如果函数超过40行,可以思索一下能不能在不影响程序结构的前提下对其进行分割。

即使一个长函数现在工作的非常好,一旦有人对其修改,有可能出现新的问题,甚至导致难以发现的错误。使函数尽量简短,以便于他在他人阅读和修改代码。

在处理代码时,你可能会发现复杂的长函数。不要害怕修改现有代码:如果证实这些代码使用/调试起来很困难,或者你只需​​要使用其中的一小段代码,考虑将其分割为更加简短并易于管理的若干函数。

4.3。引用参数

总述

所有按引用传递的参数必须加上  const

定义

在C语言中,如果函数需要修改变量的值,参数必须为指针,如  在C ++中,函数还可以声明为引用参数:  int foo(int pval)int foo(int &val)

优点

引用定义参数可以防止出现  (pval)++ 这样丑陋的代码。引用参数对于拷贝构造函数这样的应用也是必需的同时也更明确地不接受空指针

缺点

容易引起误解,因为引用在语法上是值变量却拥有指针的语义。

结论

函数参数列表中,所有引用参数都必须是  const

void  Foo const  string  in  string   out );

事实上这在Google Code是一个硬性约定:输入参数是值参或  const 引用,输出参数为指针。输入参数可以是  const 指针,但决不能是非  const 引用参数,除非特殊要求,比如  swap()

有时候,在输入形参中用针指   比   更明智。比如:const Tconst T&

  • 可能会传递空指针。
  • 函数要把指针或对地址的引用赋值给输入形参。

总而言之,大多时候输入形参往往是  用若   则说明输入侧另有处理。所以若要使用  ,则应给出相应的理由,否则会使读者感到迷惑。const T&const T*const T*

4.4。函数重载

总述

若要使用函数重载,则必须能让读者一看调用点就胸有成竹,而不用花心思猜测调用的重载函数到底是哪一种。这一规则也适用于构造函数。

定义

你可以编写一个参数类型为   的函数,然后用另一个参数类型为   的函数对其进行重载:const string&const char*

class  MyClass  { 
public
void Analyze const string text );
void 分析const char * text size_t textlen );
};

优点

通过重载参数不同的同名函数,可以令代码更直观。模板化代码需要重载,这同时也能为使用者带来便利。

缺点

如果函数单靠不同的参数类型而重载(acgtyrant注:这意味着参数数量不变),读者就得十分熟悉C ++五花八门的匹配规则,以了解匹配过程具体到底如何。另外,如果派生类只重载了某个函数的部分变体,继承语义就容易令人困惑。

结论

如果打算重载一个函数,可以试试改在函数名里加参数信息。例如,用  AppendString()和  AppendInt() 等,而不是一口气重载多个  Append()如果重载函数的目的是为了支持不同数量的同一类型参数,则优先考虑使用  std::vector 以便使用者可以用  列表初始化指定参数。

4.5。缺省参数

总述

只允许在非虚函数中使用缺省参数,且必须保证缺省参数的值始终一致。参数缺省与  函数重载  遵循同样的规则。一般情况下建议使用函数重载,尤其是在缺省函数带来的可读性提升不能弥补下文中所提到的缺点的情况下。

优点

有些函数一般情况下使用默认参数,但有时需要又使用非默认的参数。缺省参数为这样的情形提供了便利,使程序员不需要为了极少的例外情况编写大量的函数。和函数重载相比,缺省参数的语法更简洁明了,减少了大量的样板代码,也更好地区别了“必要参数”和“可选参数”。

缺点

缺省参数实际上是函数重载语义的另一种实现方式,因此所有  不应当使用函数重载的理由  也都适用于缺省参数。

虚函数调用的缺省参数取决于目标对象的静态类型,此时无法保证给定函数的所有重载声明的都是同样的缺省参数。

缺省参数是在每个调用点都要进行重新求值的,这会造成生成的代码迅速膨胀。作为读者,一般来说也更希望缺省的参数在声明时就已经被固定了,而不是在每次调用时都可能会有不同的取值。

缺省参数会干扰函数指针,导致函数签名与调用点的签名不一致。而函数重载不会导致这样的问题。

结论

对于虚函数,不允许使用缺省参数,因为在虚函数中缺省参数不一定能正常工作。如果在每个调用点缺省参数的值都有可能不同,在这种情况下缺省函数也不允许使用。(例如,不要写像   这样的代码。)void f(int n = counter++);

在其他情况下,如果缺省参数对可读性的提升远远超过了以上提及的缺点的话,可以使用缺省参数。如果仍有疑惑,就使用函数重载。

4.6。函数返回类型后置语法

总述

只有在常规写法(返回类型前置)不便于书写或不便于阅读时使用返回类型后置语法。

定义

C ++现在允许两种不同的函数声明方式。以往的写法是将返回类型置于函数名之前。例如:

int  foo int  x );

C ++ 11引入了这一新的形式。现在可以在函数名前使用  auto 关键字,在参数列表之后后置返回类型。例如:

auto  foo int  x  - >  int ;

后置返回类型为函数作用域。对于像  int 这样简单的类型,两种写法没有区别。但对于复杂的情况,例如类域中的类型声明或者以函数参数的形式书写的类型,写法的不同会造成区别。

优点

后置返回类型是显式地指定  Lambda表达式  的返回值的唯一方式。某些情况下,编译器可以自动推导出Lambda表达式的返回类型,但并不是在所有的情况下都能实现。即使编译器能够自动推导,显式地指定返回类型也能让读者更明了。

有时在已经出现了的函数参数列表之后指定返回类型,能够让书写更简单,也更易读,尤其是在返回类型依赖于模板参数时。例如:

template  < class  T  class  U >  auto  add T  t  U  u  - >  decltype t  +  u );

对比下面的例子:

template  < class  T  class  U >  decltype declval < T &> () +  declval < U &gt ;) add T  t  U  u );

缺点

后置返回类型相对来说是非常新的语法,而且在C和Java中都没有相似的写法,因此可能对读者来说比较陌生。

在已有的代码中有大量的函数声明,你不可能把它们都用新的语法重写一遍。因此实际的做法只能是使用旧的语法或者新旧混用。在这种情况下,只使用一种版本是相对来说更规整的形式。

结论

在大部分情况下,应当继续使用以往的函数声明写法,即将返回类型置于函数名前。只有在必要的时候(如Lambda表达式)或者使用后置语法能够简化书写并且提高易读性的时候才使用新的返回类型后置语法。但是后一种情况一般来说是很少见的,大部分时候都出现在相当复杂的模板代码中,而多数情况下不鼓励写这样  复杂的模板代码

7.命名约定

最重要的一致性规则是命名管理。命名的风格能让我们在不需要去查找类型声明的条件下快速地了解某个名字代表的含义:类型,变量,函数,常量,宏,等等,甚至。我们大脑中的模式匹配引擎非常依赖这些命名规则。

命名规则具有一定随意性,但相比按个人喜好命名,一致性更重要,所以无论你认为它们是否重要,规则总归是规则。

7.1。通用命名规则

总述

函数命名,变量命名,文件命名要有描述性; 少用缩写。

说明

尽可能使用描述性的命名,别心疼空间,毕竟相比之下让代码易于新读者理解更重要。不要用只有项目开发者能理解的缩写,也不要通过砍掉几个字母来缩写单词。

int  price_count_reader ;     //无缩写
int num_errors ; //“num”是一个常见的写法
int num_dns_connections ; //人人都知道“DNS”是什么
int  n ;                      //毫无意义。
int nerr ; //含糊不清的缩写。
int n_comp_conns ; //含糊不清的缩写。
int wgc_connections ; //只有贵团队知道是什么意思
int pc_reader ; //“pc”有太多可能的解释了。
int cstmr_id ; //删减了若干字母。

注意,一些特定的广为人知的缩写是允许的,例如用  i 表示迭代变量和用  T 表示模板参数。

模板参数的命名应当遵循对应的分类:类型模板参数应当遵循  类型命名  的规则,而非类型模板应当  遵循变量命名  的规则。

7.2。文件命名

总述

文件名要全部小写,可以包含下划线()或连-字符),依照项目的约定。如果没有约定,那么“ 更好

说明

可接受的文件命名示例:

C ++文件要以  .cc 结尾,头文件以  .h 结尾。专门插入文本的文件则以  .inc 结尾,参见  头文件自足

不要使用已经存在于  /usr/include 下的文件名(Yang.Y注:即编译器搜索系统头文件的路径),如  db.h

通常应尽量让文件名更加明确。  http_server_logs.h 就比  logs.h 要好。定义类时文件名一般成对出现,如  foo_bar.h 和  foo_bar.cc,对应于类  FooBar

联内必须函数放在  .h 文件中。如果内联函数比较短,就直接放在  .h 中。

7.3。类型命名

总述

类型名称的每个单词首字母均大写,不包含下划线:  MyExcitingClass,  MyExcitingEnum

说明

所有类型命名 - 类,结构体,类型定义(typedef),枚举,类型模板参数 - 均使用相同约定,即以大写字母开始,每个单词首字母均大写,不包含下划线。例如:

//类和结构体
UrlTable {
class UrlTableTester {
struct UrlTableProperties {

//类型定义
typedef hash_map < UrlTableProperties * string > PropertiesMap ;

//使用别名
使用 PropertiesMap = hash_map < UrlTableProperties * string > ;

//枚举
enum UrlTableErrors {

7.4。变量命名

总述

变量(包括函数参数)和数据成员名一律小写,单词之间用下划线连接。类的成员变量以下划线结尾,但结构体的就不用,如:  a_local_variable,  a_struct_data_member,  a_class_data_member_

说明

普通变量命名

举例:

字符串 table_name ;   //好 - 用下划线。
字符串 表名; //好 - 全小写。

字符串 tableName ; //差 - 混合大小写

类数据成员

不管是静态的还是非静态的,类数据成员都可以和普通变量一样,但要接下划线。

 TableInfo  { 

private
string table_name_ ; //好 - 后加下划线。
字符串 tablename_ ; //好。
静态 < TableInfo > * pool_ ; //好。
};

结构体变量

不管是静态的还是非静态的,结构体数据成员都可以和普通变量一样,不用像类那样接下划线:

struct  UrlTableProperties  { 
string name ;
int num_entries ;
静态 < UrlTableProperties > * ;
};

结构体与类的使用讨论,参考  结构体与类

7.5。常量命名

总述

声明为  constexpr 或  const 的变量,或在程序运行期间其值始始保持不变的,命名时以“k”开头,大小写混合。例如:

const  int  kDaysInAWeek  =  7 ;

说明

所有具有静态存储类型的变量(例如静态变量或全局变量,参见  存储类型)都应当以此方式命名。对于其他存储类型的变量,如自动变量等,这条规则是可选的。如果不采用这条规则,就按照一般的变量命名规则。

7.7。函数命名

总述

常规函数使用大小写混合,取值和设值函数则要求与变量名匹配:  MyExcitingFunction(),  MyExcitingMethod(),  my_exciting_member_variable(),  set_my_exciting_member_variable()

说明

一般来说,函数名的每个单词首字母大写(即“驼峰变量名”或“帕斯卡变量名”),没有下划线。对于首字母缩写的单词,更倾向于将它们视作一个单词进行首字母大写(例如,写作  StartRpc() 而非  StartRPC())。

AddTableEntry ()
DeleteUrl ()
OpenFileOrDie ()

(同样的命名规则同时适用于类作用域和命名空间作用域的常量,因为它们是作为API的一部分暴露对外的,因此应当让它们看起来像是一个函数,因为在这时,它们实际上是一个对象而非函数的这一事实对外不过是一个无关紧要的实现细节。)

取值和设值函数的命名与变量一致一般来说它们的名称与实际的成员变量对应,但并不强制要求。例如   与  int count()void set_count(int count)

7.7。命名空间命名

总述

命名空间以小写字母命名。最高级命名空间的名字取决于项目名称。要注意避免嵌套命名空间的名字之间和常见的顶级命名空间的名字之间发生冲突。

顶级命名空间的名称应当是项目名或者是该命名空间中的代码所属的团队的名字。命名空间中的代码,应当存放于和命名空间的名字匹配的文件夹或其子文件夹中。

注意  不使用缩写作为名称  的规则同样适用于命名空间。命名空间中的代码极少需要涉及命名空间的名称,因此没有必要在命名空间中使用缩写。

要避免嵌套的命名空间与常见的顶级命名空间发生名称冲突由于名称查找规则的存在,命名空间之间的冲突完全有可能导致编译失败。尤其是,不要创建嵌套的  std 命名空间。建议使用更独特的项目标识符(websearch::index,  websearch::index_util)而非常见的极易发生冲突的名称(比如  websearch::util)。

对于  internal 命名空间,要当心加入到同一  internal 命名空间的代码之间发生冲突(由于内部维护人员通常来自同一团队,因此常有可能导致冲突)。在这种情况下,请使用文件名以使内部名称独一无二(例如对于  frobber.h,使用  websearch::index::frobber_internal)。

7.8。枚举命名

总述

的枚举命名应当状语从句:  常量  或   harmony和谐:  kEnumName 或是  ENUM_NAME

说明

的单独枚举值应该优先采用  常量  的命名方式。但   方式的命名也。可以接受。枚举名  UrlTableErrors (以及  AlternateUrlTableErrors)是类型,所以要用大小写混合的方式。

enum  UrlTableErrors  { 
kOK = 0
kErrorOutOfMemory
kErrorMalformedInput
};
枚举 AlternateUrlTableErrors {
OK = 0
OUT_OF_MEMORY = 1
MALFORMED_INPUT = 2
};

2009年1月之前,我们一直建议采用   的方式命名枚举值。由于枚举值和宏之间的命名冲突,直接导致了很多问题。由此,这里改为优先选择常量风格的命名方式。新代码应该尽可能优先使用常量风格。但是老代码没必要切换到常量风格,除非宏风格确实会产生编译期问题。

7.9。宏命名

总述

你并不打算  使用宏,对吧?如果你一定要用,像这样命名:  MY_MACRO_THAT_SCARES_SMALL_CHILDREN

说明

参考  预处理宏 ; 通常  不应该  使用宏。如果不得不使用,其命名像枚举命名一样全部大写,使用下划线:

#define ROUND(x)… 
#define PI_ROUNDED 3.0

7.10。命名规则的特例

总述

如果你命名的实体与已有C / C ++实体相似,可参考现有命名策略。

bigopen():函数名,参照  open() 的形式

uint: typedef

bigpos:  struct 或  class,参照  pos 的形式

sparse_hash_map:STL型实体; 参照STL命名约定

LONGLONG_MAX:常量,如同 INT_MAX

8.注意

注释虽然写起来很痛苦,但对保证代码可读性至关重要。下面的规则描述了如何注释以及在哪儿注释。当然也要记住:注释固然很重要,但最好的代码应当本身就是文档。有意义的类型名和变量名,要远胜过要用注释解释的含糊不清的名字。

你写的注释是给代码读者看的,也就是下一个需要理解你的代码的人。所以慷慨些吧,下一个读者可能就是你!

8.1。注释风格

总述

使用  // 或  ,统一就好。/ /

说明

// 或   都可以; 但   常用。要在如何注释及注释风格上确保统一/ /// 

8.2。文件注释

总述

在每一个文件开头加入版权公告。

文件注释描述了该文件的内容。如果一个文件只声明,或实现或测试了一个对象,并且这个对象已经在它的声明处进行了详细的注释,那么就没有必要再加上文件注释。除此之外的其他文件都需要文件注释。

说明

法律公告和作者信息

每个文件都应该包含许可证引用。为项目选择合适的许可证版本(比如,Apache 2.0,BSD,LGPL,GPL)

如果你对原始作者的文件做了重大修改,请考虑删除原作者信息。

文件内容

如果一个  .h 文件声明了多个概念,则文件注释应当对文件的内容做一个大致的说明,同时说明各个概念之间的联系。一个一到两行的文件注释就足够了,对于每个概念的详细文档应当放在各个概念中,而不是文件注释中。

不要在  .h 和  .cc 之间复制注释,这样的注释偏离了注释的实际意义。

8.3。类注释

总述

每个类的定义都要附带一份注释,描述类的功能和用法,除非它的功能相当明显。

//遍历GargantuanTable的内容。
//示例:
// GargantuanTableIterator * iter = table-> NewIterator();
// it for(iter-> Seek(“foo”);!iter-> done(); iter-> Next()){
// process(iter-> key(),iter-> value());
//}
//删除它;
GargantuanTableIterator {

};

说明

类注释应当为读者理解如何使用与何时使用类提供足够的信息,同时应当提醒读者在正确使用此类时应当考虑的因素。如果类有任何同步前提,请用文档说明。如果该类的实例可被多线程访问,要特别注意文档说明多线程环境下相关的规则和常量使用。

如果你想用一小段代码演示这个类的基本用法或通常用法,放在类注释里也非常合适。

如果类的声明和定义分开了(例如分别放在了  .h 和  .cc 文件中),此时,描述类用法的注释应当和接口定义放在一起,描述类的操作和实现的注释应当和实现放在一起。

8.4。函数注释

总述

函数声明处的注释描述函数功能; 定义处的注释描述函数实现。

说明

函数声明

基本上每个函数声明处前都应当加上注释,描述函数的功能和用途。只有在函数的功能简单而明显时才能省略这些注释(例如,简单的取值和设值函数)。注释使用叙述式(“打开文件”)而非指令式(“打开文件”); 注释只是为了描述函数,而不是命令函数做什么。通常,注释不会描述函数如何工作。那是函数定义部分的事情。

函数声明处注释的内容:

  • 函数的输入输出。
  • 对类成员函数而言:函数调用期间对象是否需要保持引用参数,是否会释放这些参数。
  • 函数是否分配了必须由调用者释放的空间。
  • 参数是否可以为空指针。
  • 是否存在函数使用上的性能隐患。
  • 如果函数是可重入的,其同步提提是什么?

举例如下:

//返回此表的迭代器。
当迭代器完成时,它是
客户端的责任//并且一旦
创建
迭代器的GargantuanTable对象被删除,它就不能使用迭代器//
//迭代器最初位于表的开始位置。
//
//此方法等同于:
// Iterator * iter = table-> NewIterator();
// iter-> Seek(“”);
//返回iter;
//如果您要立即寻找到
返回的迭代器
中的其他位置,则使用NewIterator()会更快,并避免额外的查找。
Iterator * GetIterator () const;

但也要避免罗罗嗦嗦,或者对显着易见的内容进行说明。下面的注释就没有必要加上“否则返回false”,因为已经暗含其中了:

//如果表不能包含更多条目,则返回true。
bool IsTableFull ();

注释函数重载时,注释的重点应该是函数中被重载的部分,而不是简单的重复被重载的函数的注释。多数情况下,函数重载不需要额外的文档,因此也没有必要加上注释。

注释构造/析构函数,切记读代码的人知道构造/析构函数的所有功能,所以“销毁这一对象”这样的注释是没有意义的。你应该注意的是注意构造函数对参数做了什么(例如,是否取得指针所有权)以及析构函数清理了什么。如果都是些无关紧要的内容,直接省掉注释。析构函数前没有注释是很正常的。

函数定义

如果函数的实现过程中用到了很巧妙的方式,那么在函数定义处应当加上解释性的注释。例如,你所使用的编程技巧,实现的大致步骤,或解释如此实现的理由。举个例子,你可以说明为什么函数的前半部分要加锁而后半部分不需要。

不要  从  .h 文件或其他地方的函数声明处直接复制注释。简要重述函数功能是可以的,但注释重点要放在如何实现上。

8.5。变量注释

总述

通常变量名本身足以很好说明变量用途。某些情况下,也需要额外的注释说明。

说明

类数据成员

每个类数据成员(也叫实例变量或成员变量)都应该用注释说明用途。如果有非变量的参数(例如特殊值,数据成员之间的关系,生命周期等)不能够使用类型与变量名明确表达,则应当加上注释。然而,如果变量类型与变量名已经足够描述一个变量,那么就不需要加上注释。

特别地,如果变量可以接受  NULL 或  -1 等警戒值,须加以说明。比如:

private 
//用于限制检查表访问。-1意味着
//我们还不知道表中有多少个条目。
int num_total_entries_ ;

全局变量

和数据成员一样,所有全局变量也要注释说明含义及用途,以及作为全局变量的原因。比如:

//在此回归测试中我们经历的测试用例的总数。
const int kNumTestCases = 6 ;

8.6。实现注释

总述

对于代码中巧妙的,晦涩的,有趣的,重要的地方加以注释。

说明

代码前注释

巧妙或复杂的代码段前要加注释。比如:

//将结果除以2,考虑到x 
//包含来自add的进位。
for int i = 0 ; i < result - > size (); i ++ {
x = x << 8 + * result )[ i ];
* 结果)[ i ] = x >> 1 ;
x &= 1 ;
}

行注释

比较隐晦的地方要在行尾加入注释。在行尾空两格进行注释。比如:

//如果我们有足够的内存,也可以对数据部分进行mmap。
mmap_budget = max < int64 > 0 mmap_budget - index_ - > length ());
if mmap_budget > = data_size_ && MmapData mmap_chunk_bytes mlock ))
return ; //错误已经记录。

注意,这里用了两段注释分别描述这段代码的作用,并提示函数返回错误已经被记入日志。

如果你需要连续进行多行注释,可以使之对齐获得更好的可读性:

DoSomething ();                   //在这里发表评论,以便评论排成一行。
DoSomethingElseThatIsLonger (); //代码和注释之间有两个空格。
{ //允许打开一个新的作用域时,在注释之前的一个空格
// //因此注释与下面的注释和代码一起排列。
DoSomethingElse (); //通常在行注释之前有两个空格。
}
std :: vector < string > list {
//支撑列表中的注释描述下一个元素…
“First item”
// …并且应该适当地对齐。
“第二项” };
做一点事(); / 对于尾部块注释,一个空间可以。 /

函数参数注释

如果函数参数的意义不明显,考虑用下面的方式进行弥补:

  • 如果参数是一个字面常量,并且这一常量在多处函数调用中被使用,用以推断它们一致,你应该用一个常量名让这个约定变得更明显,并且保证这一约定不会被打破。
  • 考虑更改函数的签名,让某个  bool 类型的参数变为  enum 类型,这样可以让这个参数的值表达其意义。
  • 如果某个函数有多个配置选项,你可以考虑定义一个类或结构体以保存所有的选项,并传入类或结构体的实例。这样的方法有许多优点,例如这样的选项可以在调用处用变量名引用,这样就能清晰地表明其意义。同时也减少了函数参数的数量,使得函数调用更易读也易写。除此之外,以这样的方式,如果你使用其他的选项,就无需对调用点进行更改。
  • 用具名变量代替大段而复杂的嵌套表达式。
  • 万不得已时,才考虑在调用点用注释阐明参数的意义。

比如下面的示例的对比:

//这些论据是什么?
const DecimalNumber product = CalculateProduct values 7 false nullptr );

ProductOptions  选项; 
选项set_precision_decimals 7 );
选项set_use_cache ProductOptions :: kDontUseCache );
const DecimalNumber product =
CalculateProduct values options / * completion_callback = * / nullptr );

哪个更清晰一目了然。

不允许的行为

不要描述显而易见的现象,  永远不要  用自然语言翻译代码作为注释,除非即使对深入理解C ++的读者来说代码的行为都是不明显的。要假设读代码的人C ++水平比你高,即便他/她可能不知道你的用意:

你所提供的注释应当解释代码  为什么  要这么做和代码的目的,或者最好是让代码自文档化。

比较这样的注释:

//在矢量中查找元素。< - 差:这太明显了!
自动 ITER = STD :: 找到v 开始(), v (), 元素);
如果 ITER =! v ()) {
过程元件);
}

和这样的注释:

//处理“元素”,除非它已经被处理。
自动 ITER = STD :: 找到v 开始(), v (), 元素);
如果 ITER =! v ()) {
过程元件);
}

自文档化的代码根本就不需要注释。上面例子中的注释对下面的代码来说就是毫无必要的:

if  IsAlreadyProcessed element )) { 
Process element );
}

8.8。标点,拼写和语法

总述

注意标点,拼写和语法; 写的好的注释比差的要易读的多。

说明

注释的通常写法是包含正确大小写和结尾句号的完整叙述性语句。大多数情况下,完整的句子比句子片段可读性更高。短一点的注释,比如代码行尾注释,可以随意点,但依然要注意风格的一致性。

虽然被别人指出该用分号时却用了逗号多少有些尴尬,但清晰易读的代码还是很重要的。正确的标点,拼写和语法对此会有很大帮助。

8.8。TODO注释

总述

对那些临时的,短期的解决方案,或已经够好,但仍不完美的代码使用  TODO 注释。

TODO 注意要使用全大写的字符串  TODO,在随后的圆括号里写上你的名字,邮件地址,bug ID,或其它身份标识和与这一  TODO 相关的问题。主要目的是让添加注释的人(也是可以请求提供更多细节的人)可根据规范的  TODO 格式进行查找。添加  TODO 注释并不意味着你要自己来修正,因此当你加上带有姓名的时候  TODO ,一般都是写上自己的名字。

// TODO([email protected]):这里使用“*”作为连接运算符。
// TODO(Zeke)将其改为使用关系。
// TODO(错误12345):删除“最后访问者”功能

如果加  TODO 是为了在“将来某一天做某事”,可以附上一个非常明确的时间“Fix by November 2005”),或者一个明确的事项(“所有客户端都可以处理XML响应时删除此代码。”) 。

8.9。弃用注释

总述

通过弃用注释(DEPRECATED 评论)以标记某接口点已弃用。

您可以写上包含全大写的  DEPRECATED 注释,以标记某接口为弃用状态。注释可以放在接口声明前,或者同一行。

DEPRECATED 一词后,在  括号中留下您的名字,邮箱地址以及其他身份标识。

弃用注释应当包涵简短而清晰的指引,以帮助其他人修复其调用点。在C ++中,你可以将一个弃用函数改造成一个内联函数,这一函数将调用新的接口。

DEPRECATED 仅仅标记接口为并  不允许大家不约而同地弃用,您还得亲自主动修正调用点(callsites),或是找个帮手。

修正好的代码应该不会再涉及弃用接口点了,着实改用新接口点。如果您不知从何下手,可以找标记弃用注释的当事人一起商量。

9.格式

每个人都可能有自己的代码风格和格式,但如果一个项目中的所有人都遵循同一风格的话,这个项目就能更顺利地进行。每个人未必能同意下述的每一处格式规则,而且其中的不少规则需要一定时间的适应,但整个项目服从统一的编程风格是很重要的,只有这样才能让所有人轻松地阅读和理解代码。

为了帮助你正确的格式化代码,我们写了一个  emacs配置文件

9.1。行长度

总述

每一行代码字符数不超过80。

我们也认识到这条规则是有争议的,但很多已有代码都遵照这一规则,因此我们感觉一致性更重要。

优点

提倡该原则的人认为强迫他们调整编辑器窗口大小是很野蛮的行为。很多人同时并排开几个代码窗口,根本没有多余的空间拉伸窗口。大家都把窗口最大尺寸加以限定,并且80列宽是传统标准。那么为什么要改变呢?

缺点

反对该原则的人则认为更宽的代码行更易阅读。80列的限制是上个世纪60年代的大型机的古板缺陷; 现代设备具有更宽的显示屏,可以很轻松地显示更多代码。

结论

80个字符是最大值。

如果无法在不伤害易读性的条件下进行断行,那么注释行可以超过80个字符,这样可以方便复制粘贴。例如,带有命令示例或URL的行可以超过80个字符。

长所有游戏的路径  #include 语句可以超出80列。

文件头保护  可以无视该原则。

9.2。非ASCII字符

总述

尽量不使用非ASCII字符,使用时必须使用UTF-8编码。

说明

即使是英文,也不应将用户界面的文本硬编码到源代码中,因此非ASCII字符应当很少被用到。特殊情况下可以适当包含此类字符。例如,代码分析外部数据文件时,可以适当硬编码数据文件中作为分隔符的非ASCII字符串; 更常见的是(不需要本地化的)单元测试代码可能包含非ASCII字符串。此类情况下,应使用UTF-8编码,因为很多工具都可以理解和处理UTF-8编码。

十六进制编码也可以,能增强可读性的情况下尤其鼓鼓 - 比如  “\xEF\xBB\xBF”,或者更简洁地写作  u8"\uFEFF",在Unicode中是  零宽度无间断  的间隔符号,如果不用十六进制直接放在UTF -8格式的源文件中,是看不到的。

(Yang.Y注:  “\xEF\xBB\xBF” 通常用作带编码标记的UTF-8)

使用  u8 前缀把带  uXXXX 转义序列的字符串字面值编码成UTF-8。不要用在本身就带UTF-8字符的字符串字面值上,因为如果编译器不把源代码识别成UTF-8,输出就会出错。

别用C ++ 11的  char16_t 和  char32_t,它们和UTF-8文本没有关系,  wchar_t 同理,除非你写的代码要调用Windows API,后者广泛使用了  wchar_t

9.3。空格还是制表位

总述

<span style="font-family:‘Microsoft YaHei’

				版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载;https://blog.csdn.net/csdn_baotai					https://blog.csdn.net/csdn_baotai/article/details/80304636				</div>
							            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d7e2a68c7c.css">
					<div class="htmledit_views" id="content_views">
            <h1 style="margin-top:0px;background-color:rgb(242,242,242);"><a name="t0"></a><span style="font-family:'Microsoft YaHei';font-size:24px;color:#339999;"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">google开源</span></span></span></span><span style="vertical-align:inherit;"><span style="vertical-align:inherit;"> C / C ++项目代码规范</span></span></span></h1><h1 style="margin-top:0px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><a name="t1"></a><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">1.头文件</span></span></h1><p style="line-height:24px;margin-bottom:24px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">每通常一个&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件都有一个对应的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件。</span><span style="vertical-align:inherit;">也有一些常见例外,如单元测试代码和只包含&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">main()</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;函数的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">正确使用头文件可令代码在可读性,文件大小和性能上大为改观。</span></span></p><p style="line-height:24px;margin-bottom:24px;color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">下面的规则将引导你规避使用头文件时的各种陷阱。</span></span></p><div class="section" style="color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="font-family:'Microsoft YaHei';"><span></span></span><h2 style="margin-top:0px;"><a name="t2"></a><span style="font-family:'Microsoft YaHei';vertical-align:inherit;"><span style="vertical-align:inherit;">1.1。</span><span style="vertical-align:inherit;">自包含的头文件</span></span></h2><div class="admonition tip" style="padding:12px;line-height:24px;margin-bottom:24px;background:rgb(219,250,244);"><p class="first admonition-title" style="line-height:1;margin:-12px -12px 12px;font-weight:bold;color:rgb(255,255,255);background:rgb(26,188,156);padding:6px 12px;"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">TIP</span></span></p><p class="last" style="line-height:24px;margin-bottom:0px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">头文件应该能够自给自足(自包含的,也就是可以作为第一个头文件被引入</span><span style="vertical-align:inherit;">),以&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;结尾。至于用来插入文本的文件,说到底它们并不是头文件,所以以应&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.inc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;结尾不允许。出分离&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">-inl.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;头文件的做法。</span></span></span></p></div><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">所有头文件要能够自给自足。换言之,用户和重构工具不需要为特别场合而包含额外的头文件。详言之,一个头文件要有&nbsp; </span></span><a class="reference internal" href="http://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/headers/#define-guard" rel="nofollow" style="color:rgb(155,89,182);" target="_blank"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">1.2。</span><span style="vertical-align:inherit;">#define保护</span></span></a><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">,统计包含它所需要的其它头文件,也不要求定义任何特别的符号。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">不过有一个例外,即一个文件并不是自足的,而是作为文本插入到代码某处。或者,文件内容实际上是其它头文件的特定平台</span><span style="vertical-align:inherit;">(特定于平台)扩展部分,这些文件就要用&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.inc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件扩展名。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">如果&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件声明了一个模板或内联函数</span><span style="vertical-align:inherit;">,同时也在该文件加以定义。有用凡是到这些的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件,就得统统包含该头文件,否则程序可能会在构建中链接失败</span><span style="vertical-align:inherit;">。不要把这些定义放到分离的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">-inl.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件里(译者注:过去该规范曾提倡把定义放到-inl.h里过)。</span></span></span></p><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">有个例外:如果某函数模板为所有相关模板参数显式实例化</span><span style="vertical-align:inherit;">,或本身就是某类的一个私有成员,它就那么定义只能在实例化该模板的&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">.cc</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;文件里。</span></span></span></p></div><div class="section" style="color:rgb(64,64,64);background-color:rgb(242,242,242);"><span style="font-family:'Microsoft YaHei';"><span></span></span><h2 style="margin-top:0px;"><a name="t3"></a><span style="font-family:'Microsoft YaHei';vertical-align:inherit;"><span style="vertical-align:inherit;">1.2。</span><span style="vertical-align:inherit;">#define保护</span></span></h2><div class="admonition tip" style="padding:12px;line-height:24px;margin-bottom:24px;background:rgb(219,250,244);"><p class="first admonition-title" style="line-height:1;margin:-12px -12px 12px;font-weight:bold;color:rgb(255,255,255);background:rgb(26,188,156);padding:6px 12px;"><span style="vertical-align:inherit;"><span style="font-family:'Microsoft YaHei';vertical-align:inherit;">TIP</span></span></p><p class="last" style="line-height:24px;margin-bottom:0px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">所有头文件都应该使用&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">#define</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;来防止头文件被多重包含,命名格式当是:&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">&lt;PROJECT&gt;_&lt;PATH&gt;_&lt;FILE&gt;_H_</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;。</span></span></span></p></div><p style="line-height:24px;margin-bottom:24px;"><span style="font-family:'Microsoft YaHei';"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">为保证唯一性,头文件的命名应该基于所有项目源代码树的全路径。</span><span style="vertical-align:inherit;">例如,项目&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">foo</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;中的头文件&nbsp; </span></span><code class="docutils literal" style="font-size:12.8px;white-space:nowrap;max-width:100%;background:rgb(242,242,242);border:1px solid rgb(225,228,229);padding:2px 5px;color:rgb(231,76,60);"><span class="pre">foo/src/bar/baz.h</span></code><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">&nbsp;可按如下方式保护:</span></span></span></p><div class="highlight-c++" style="border:1px solid rgb(225,228,229);padding:0px;margin:1px 0px 24px;"><div class="highlight" style="border:none;padding:0px;margin:0px;"><pre style="margin-bottom:0px;padding:12px;line-height:normal;"><span style="font-family:'Microsoft YaHei';"><span class="cp"><span style="vertical-align:inherit;"><span style="vertical-align:inherit;">#ifndef FOO_BAR_BAZ_H_ </span></span></span>

猜你喜欢

转载自blog.csdn.net/csshuke/article/details/85299115