Google C++编程规范(一)————(头文件篇)
2011-03-14 22:56
288 查看
开始在csdn上写一些文章了; 就拿《Google C++ Style Guide》开刀吧 :);本文不是完全一字一句对应翻译。而是本人边看边写个人理解。
头文件一般是用来给别的文件需要引用其中的变量或函数使用,google在这里从代码阅读和维护角度强调其重要性
搞这么复杂的原因是防止冲突:举个例子说:大家都喜欢用type.h或common.h,base.h 这些一目了然的名字谁都抢着用;
如果这个工程只有一个人写,还好说。这些名字自己想怎么用就怎么用。但是如果是一个庞大的工程,有几个人合作写。
结果程序员A写基础库的人用了base.h, 另外一个程序员B使用A写基础库,程序员B自己工程里面也有一个base.h;
如果大家都这样使用_BASE_H_,这样编译的时候就产生冲突了。所以最好加上前缀区分开。google使用的是用
工程+目录为前缀。不过本人习惯不是这样,使用目录一个不好的地方时,代码文件目录有时候经常重新规划,
从这个目录移到另一个目录,按照google这样定义,就要把代码文件翻出来,对宏一个个修改了。岂不是很麻烦
改成[/code]
[/code]
头文件(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.
相关文章推荐
- 一张图总结Google C++编程规范(Google C++ Style Guide)
- Google C++编程规范 – 第二十一条 -《-inl.h文件》
- Google C++编程规范(一)
- Google C++编程规范 – 第十九条 -《前置声明》
- Google-C++编程规范(完整)
- 一张图总结Google C++编程规范(Google C++ Style Guide)
- 一张图总结Google C++编程规范(Google C++ Style Guide)
- 一张图总结Google C++编程规范(Google C++ Style Guide)
- Google C++编程规范学习--头文件
- Google c++编程规范-----注释
- 对Google C++编程规范的理解和实践
- Google C++编程规范 1 头文件
- 一张图总结Google C++编程规范(Google C++ Style Guide)
- GOOGLE C++编程规范
- 一张图总结Google C++编程规范(Google C++ Style Guide)
- Google C++编程规范
- 一张图总结Google C++编程规范(Google C++ Style Guide)
- Google C++编程规范
- Google C++编程规范 1.2
- Google-C++编程规范(完整)