Chinaunix首页 | 论坛 | 博客
  • 博客访问: 12409
  • 博文数量: 3
  • 博客积分: 85
  • 博客等级: 民兵
  • 技术积分: 35
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-14 20:32
文章分类
文章存档

2012年(3)

我的朋友

分类: C/C++

2012-06-14 21:36:34

最近在给公司的童鞋们做培训,在做代码风格培训的时候,刚好顺带把Google的代码规范翻译了。把译文逐步贴上来吧。

背景:

C++是Google许多开源项目所主要采用的开发语言。众所周知,C++拥有许多强大的特性,但这也造就了C++高度的复杂性,以至于使得C++编码更易出错以及较难阅读。


本手册编写的目的正是去尝试通过约定代码中“要做”和“不要做的”规范来解决这种复杂性。使得代码既可以依然使用到语言强大的特性,又易于管理。


代码风格,也叫“代码可读性”,是我们规范我们代码的准则。但其实“风格”这个词并不够精准,因为这些原则所涵盖的内容远远不仅是源代码的格式化。


保证代码易于管理的其中一个行之有效的方法就是强制要求代码保持“一致性”。让一名程序员可以快速的阅读和理解另外一人所写的代码是非常重要的。保持统一的代码风格和遵循一致的代码编写规范意味着我们可以更容易的实现所谓“模式匹配”以使我们从大量的变量中快速明白他们是什么以及他们有哪些共同之处。


发布这篇文章的另外一个考虑是我们所说的“C++膨胀”。C++是一门拥有众多特性的庞大的语言。然而在一些场景下,出于保持代码简介和避免更多的共通性错误,我们不得不被约束甚至是禁止使用部分这些特性。这份文档罗列出了被禁止使用的这些特性并解释了为什么他们被禁止使用。


NOTE:这份文档并不是一份C++指引,我们假设这份文档的读者已经十分熟悉这门语言。


Header Files

一般说来,每一个.cc的文件都关联着一个.h文件。但这也有一些例外,比如单元测试文件或者一些小的只包含main函数的.cc文件。


改善头文件的使用方法能对你代码的可读性、大小、表现带来重大的改观。如下的规则会引导你如何正确的使用头文件并绕过一些陷阱:


  • #define 警戒常量声明

所有的头文件都应该包含#define警戒常量(#define guard)以避免重复嵌套的问题。警戒常量的声明应遵循如下格式:

<项目名/PROJECT>_<文件路径/PATH>_<文件名/FILE>_H_

为了保证唯一性,文件路径应该为文件在该项目中的绝对路径。举例说明,项目foo的文件foo/src/bar/baz.h应当进行如下的警戒常量声明:

#ifndef FOO_BAR_BAZ_H_

#define FOO_BAR_BAZ_H_

...

#endif //FOO_BAR_BAZ_H_


  • 头文件的依赖性

应当充分使用“预声明”以最少的#include头文件。


当你include了一个头文件的时候,你相当于对你的代码引入了一个依赖性,这意味着每当任何一个头文件被改变,你的执行代码也将需要被重新编译一次。同样,如果你的头文件也包括了其他的头文件,那任何对这些文件的改变也将引起代码的重编译。因此,我们应当最小化include的次数,特别是在头文件中include其他头文件。


使用“预声明”可以显著的减少文件包含的次数。举例来说,如果你的头文件需要声明一个File类型的变量但并没有真正的去使用它,那么你可以仅在你的头文件中声明一句:class File;而不需要去#include “file/base/file.h”


那么我们该如何在头文件中使用Foo类而不需要访问它的定义(definition)呢?

  • 以指针或者引用的方式声明成员变量:Foo* or Foo&
  • 我们可以声明(但不是定义)以Foo为返回值或者参数的函数
  • 我们可以声明类别为Foo的静态成员变量,这是因为静态成员变量是在类外被定义的。

但是如果头文件中定义的类是派生自Foo或者需要有一个类别为Foo的成员变量(非指针类型),你将必须引用Foo类别的头文件。


针对这个问题,一般我们可以通过使用该类别的指针而非其直接的对象成员已解决。但这将就一定的可能性会导致代码复杂度的增加或者效率的下降,因此,如果你仅仅是因为想要降低include的次数而这么做时,不要这么做。


当然,.cc文件中必须要包含对应的若干个头文件。


  • inline Functions(内联函数)
  • 只有当你的函数很小(10行以内)的时候,才能将他们声明为inline(内联)。请注意,隐式的析构函数的调用可能会使得你看起来不超过10行的代码远超过10行!
  • 不要在inline函数的定义中出现循环或者switch语句
  • 为了更好的效率方面的表现,成员访问器、累加器等函数应声明为inline
  • 应当注意的是,有些时候即便一个函数被声明为inline,编译器并不会真正的将其inline。举例来说,虚函数或者递归函数将不会被编译器inline。
  • -inl.h 文件

当你的头文件声明中需要有大量的inline函数的时候,将这些inline函数的定义放入-inl.h结尾的头文件中而不是.cc文件中。



函数参数的顺序

当定义一个函数的时候,参数的顺序应该为:输入->输出。


C++的函数参数要么呢是给函数指定了输入,要么是函数的输出,要么既是输入也是输出。一般来说,作为输入的参数应该是const引用,以确保在函数运行时不会对其值进行改变,而输出参数则是非const指针。当对参数顺序进行排序的时候,应当将所有输入参数放在输出参数之前。特别指出的是,不要仅仅因为一个参数是新加的就将新参数放在参数表的最后,应当将其按照上述原则放在合适的位置。


当然,这不是一个强制性的规则,同样对效率上也没有什么提升,仅为了增加代码可读性而已。



头文件的命名和包含顺序

为了提升可读性以及避免隐含的依赖性,应按照“C库函数,C++库函数,其他库函数,你自己的头文件”这样的顺序对头文件进行include

阅读(8630) | 评论(0) | 转发(0) |
0

上一篇:开博首言

下一篇:SVN常用命令

给主人留下些什么吧!~~