您的位置:首页 > 编程语言 > C语言/C++

Google C++编程规范(一)————(头文件篇)

2011-03-14 22:56 288 查看
开始在csdn上写一些文章了; 就拿《Google C++ Style Guide》开刀吧 :);本文不是完全一字一句对应翻译。而是本人边看边写个人理解。

头文件(Header Files)

一般来说,.c/.cpp/.cxx 等文件都最好有一个.h文件;这样便于代码阅读和维护。当然可以例外,像一些只有一个main函数的小的源文件,就不需要额外增加头文件,如果增加,反而显得画蛇添足。

头文件一般是用来给别的文件需要引用其中的变量或函数使用,google在这里从代码阅读和维护角度强调其重要性

#define防护

#define一般用来防止重复包含导致编译时好重复编译。一般在头文件中这样使用,例如foo/src/bar/baz.h文件    大概格式是<PROJECT>_<PATH>_<FILE>_H_
[code]#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_

...

#endif  // FOO_BAR_BAZ_H_


搞这么复杂的原因是防止冲突:举个例子说:大家都喜欢用type.h或common.h,base.h 这些一目了然的名字谁都抢着用;

如果这个工程只有一个人写,还好说。这些名字自己想怎么用就怎么用。但是如果是一个庞大的工程,有几个人合作写。

结果程序员A写基础库的人用了base.h, 另外一个程序员B使用A写基础库,程序员B自己工程里面也有一个base.h;

如果大家都这样使用_BASE_H_,这样编译的时候就产生冲突了。所以最好加上前缀区分开。google使用的是用

工程+目录为前缀。不过本人习惯不是这样,使用目录一个不好的地方时,代码文件目录有时候经常重新规划,

从这个目录移到另一个目录,按照google这样定义,就要把代码文件翻出来,对宏一个个修改了。岂不是很麻烦

头文件依赖

尽量最小化包含头文件关系,因为如果使用#include,头文件做一点修改,就会引起包含它的文件

重编译,这样会浪费大量工作时间。有一个避免的方法是使用前向申明;

#include "foo.h"

改成[/code]
class foo


并不是所有include地方都可以把#include改成前置申明。只有下面这些情况可以使用

1、成员变量使用指针或引用类型[code]Foo*
or
Foo&
. 而不是
Foo;

2、函数参数或返回值使用Foo类型 或者 构造函数的参数是隐式转化的时候

3、使用Foo类型的变量是静态变量。

另 一方面,如果你的类继承自Foo或者你有一个类数据成员是Foo,那就必须包含Foo的头文件。

有些时候,使用指针(scoped_ptr 更佳)成员而不是对象成员(object member)是明智的。然而这却降低了代码的可读性,并且导致性能损失。、

所以,如果这么做的目的只是减少头文件中的#include,那就别这么做。当然,.cpp文件必须需要它所使用的类的定义,所以它会#include比较

多的头文件

为什么有的地方需要使用前置申明,有的地方不能使用呢?归根到底是要看使用的地方在编译的时候是否需要了解Foo类的内部结构,如一个成员

变量 Foo member;编译的时候,需要计算该变量占用的内存大小,这样必须要知道Foo类的内部细节,必须使用#include,而当变量是

Foo * member时候;编译的时候编译器知道不管Foo如果变化,此指针始终占用4个直接,可以不用了解Foo类的内部细节,直接分配计算变量

占用空间。

[/code]


内联函数

内联函数用来定义一些小函数,一般小于10代码的函数,适合使用内联函数,内联函数编译时直接在调用的地方展开,没有函数

出栈入栈的开销,所以不使用内联的时候要高效一点。但是由于是直接展开,违背了代码重用的原则,导致代码空间膨胀。

其实内联函数就是一种用空间换取时间的做法。

几个地方最好不要使用内联函数

1、析构函数,析构函数往往比看起来大很多,因为它们会隐式的调用成员或者基类的析构函 数。另外析构函数往往是虚函数。

2、switch和循环的函数

3、虚函数和递归函数


inl.h文件

当你需要使用复杂的内联函数时,你可以使用文件名 后缀为-inl.h的文件来定义它。

内联函数的定义要放在头文件里,这样编译器在函数调用点才能访问到定义用于内联。然而,函数的实现代码通常放在.cc中,而且我 们也不喜欢把太多的实际代码放在.h文件中,除非这么做有利于可读性或性能。

如果一个内联函数的定义很短, 里面几乎没有任何逻辑,你应该把这样的定义代码放到.h文件中


函数参数顺序

定义函数参数的顺序:先输入参数,再输出参数。

将纯输入参数放在任何输出参数之前。尤其不要因为一个参数是新添加的,就把它放在函数参数的最后,要将纯输入参数 放在输出参数之前。

这不是个硬性规则。那种既是输入又是输出的参数。自己取舍吧:)


文件包含的名字和顺序

使用标准顺序以保证可读性,并且避免隐藏的依赖:C库,C++库,其他库的.h,你的项目的.h。


所有项目的头文件应作为项目源文件目录的后代列出,不要使用UNIX中的目录快捷方式 . (当前目录)和 .. (父目录)。
举个例子,google-awesome-project/src/base/logging.h应该以#include “base/logging.h”的格式包含。
在每个部分(section)中,根据字母顺序排列是不错的方式。

举个例子,google-awesome-project/src/foo/internal/fooserver.cc中 的文件包含顺 序可能是这样:

#include "foo/public/fooserver.h"  // Preferred location.

#include <sys/types.h>
#include <unistd.h>

#include <hash_map>
#include <vector>

#include "base/basictypes.h"
#include "base/commandlineflags.h"
#include "foo/public/bar.h"


顺序规则

foo/public/fooserver.h (preferred location — 保证该头文件能独立编译,所以放在首要位置).


C system files.

C++ system files.

Other libraries'
.h
files.

Your project's
.h
files.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: