转载请注明出处<http://blog.youkuaiyun.com/qianqin_2014/article/details/51354434>
一、头文件
通常,每一个.cc 文件(C++的源文件)都有一个对应的.h 文件(头文件),也有一些例 外,如单元测试代码和只包含 main()的.cc 文件。
正确使用头文件可令代码在可读性、文件大小和性能上大为改观。 下面的规则将引导你规避使用头文件时的各种麻烦。
1. #define 的保护
所有头文件都应该使用#define 防止头文件被多重包含(multiple inclusion),命名格式当是:<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_
2. 头文件依赖
- 将数据成员类型声明为 Foo *或 Foo &;
- 参数、返回值类型为 Foo 的函数只是声明(但不定义实现);
- 静态数据成员的类型可以被声明为 Foo,因为静态数据成员的定义在类定义之外。
有时,使用指针成员(pointer members,如果是 scoped_ptr 更好)替代 对象 成员(object members)的确更有意义。然而,这样的做法会降低代码可读性及执行效率。如果仅仅为了少包含头文件,还是不要这样替代的好。
当然,.cc 文件无论如何都需要所使用类的定义部分,自然也就会包含若干头文件。 译者注:能依赖声明的就不要依赖定义。
注释:
于是在VC下做了下测试,先自行建立Foo.h,Foo.cpp文件,里面定义一个类CFoo,不用管怎么定义,随便都行,然后建议main.cpp,在里面测试:
class CFoo;
class test
{
public:
/*1*/ CFoo func(CFoo foo);//ok
/*2*/ static CFoo sub;//ok
/*3*/ CFoo& foo1;//ok
/*4*/ CFoo* pfoo1;//ok
/*5*/ CFoo foo; //error
};
之前都是直接include Foo.h 文件,这次不引用,而是声明一下CFoo类。下面看test类的声明。
1、正确。说明了规范中第2点,函数参数和返回值只是声明。
2、正确。说明了规范中第3点,静态数据成员的类型可以被声明为Foo,因为静态数据成员的定义在类定义之外。
3、4、正确。
5错误。说明了规范中第1点,非静态的数据成员必须是指针或引用,否则需要依赖定义,其实也好理解,非静态表示每个实例都占有内存,必然需要知道内存的大小,没有定义怎么能知道呢?
3. 内联函数
只有当函数只有 10 行甚至更少时才会将其定义为内联函数(inline function)。
定义(Definition):当函数被声明为内联函数之后,编译器可能会将其内联展开,无需按通常的函数调用机制调用内联函数。
4. -inl.h 文件
复杂的内联函数的定义,应放在后缀名为-inl.h 的头文件中。
在头文件中给出内联函数的定义,可令编译器将其在调用处内联展开。然而, 实现代码应完全放到.cc 文件中,我们不希望.h 文件中出现太多实现代码,除非这样做在可读性和效率上 有明显优势。
如果内联函数的定义比较短小、逻辑比较简单,其实现代码可以放在.h 文件中。例如,存取函数的实现理所当然都放在类定义中。出于实现和调用的方便,较复杂的内联函数也可以 放到.h 文件中,如果你觉得这样会使头文件显得笨重,还可以将其分离到单独的-inl.h 中。 这样即把实现和类定义分离开来,当需要时包含实现所在的-inl.h 即可。
-inl.h 文件还可用于函数模板的定义,从而使得模板定义可读性增强。 要提醒的一点是,-inl.h 和其他头文件一样,也需要#define 保护。
5. 函数参数顺序(Function Parameter Ordering)
定义函数时,参数顺序为:输入参数在前,输出参数在后。
C/C++函数参数分为输入参数和输出参数两种,有时输入参数也会输出(译者注:值被修改时)。输入参数一般传值或常数引用(const references),输出参数或输入/输出参数为非常量指针(non-const pointers)。对参数排序时,将所有输入参数置于输出参数之前。不要仅仅因为是新添加的参数,就将其置于最后,而应该依然置于输出参数之前。
这一点并不是必须遵循的规则,输入/输出两用参数(通常是类/结构体变量)混在其中,会 使得规则难以遵循。
6. 包含文件的名称及次序
将包含次序标准化可增强可读性、避免隐藏依赖(hidden dependencies,译者注:隐藏 依赖主要是指包含的文件中编译时),次序如下:C 库 、C++库、其他库的.h、项目内的.h。
#include "base/logging.h"
dir/foo.cc 的主要作用是执行或测试 dir2/foo2.h 的功能,foo.cc 中包含头文件的次序如 下:
dir2/foo2.h(优先位置,详情如下)
C 系统文件
C++系统文件
其他库头文件
本项目内头文件
这种排序方式可有效减少隐藏依赖,我们希望每一个头文件独立编译。最简单的实现方式是将其作为第一个.h 文件包含在对应的.cc 中。
dir/foo.cc 和 dir2/foo2.h 通常位于相同目录下(像 base/basictypes_unittest.cc 和base/basictypes.h),但也可在不同目录下。相同目录下头文件按字母序是不错的选择。
#include "foo/public/fooserver.h" // 优先位置
#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"
注释:
<http://www.cnblogs.com/clever101/archive/2011/08/21/2147892.html>
转载请注明出处<http://blog.youkuaiyun.com/qianqin_2014/article/details/51354434>