原则1.1 头文件中适合放置接口的声明,不适合放置实现。 说明:头文件是模块(Module)或单元(Unit)的对外接口。头文件中应放置对外部的声明,如对外提供的函数声明、宏定义、类型定义等。 原则1.2 头文件应当职责单一。 说明:头文件过于复杂,依赖过于复杂是导致编译时间过长的主要原因。很多现有代码中头文件过大,职责过多,再加上循环依赖的问题,可能导致为了在.c中使用一个宏,而包含十几个头文件。 原则1.3 头文件应向稳定的方向包含。 说明:头文件的包含关系是一种依赖,一般来说,应当让不稳定的模块依赖稳定的模块,从而当不稳定的模块发生变化时,不会影响(编译)稳定的模块。 规则1.1 每一个.c文件应有一个同名.h文件,用于声明需要对外公开的接口。 说明:如果一个.c文件不需要对外公布任何接口,则其就不应当存在,除非它是程序的入口,如main函数所在的文件。 规则1.2 禁止头文件循环依赖。 说明:头文件循环依赖,指a.h包含b.h,b.h包含c.h,c.h包含a.h之类导致任何一个头文件修改,都导致所有包含了a.h/b.h/c.h的代码全部重新编译一遍。 而如果是单向依赖,如a.h包含b.h,b.h包含c.h,而c.h不包含任何头文件,则修改a.h不会导致包含了b.h/c.h的源代码重新编译。 规则1.3 .c/.h文件禁止包含用不到的头文件。 说明:很多系统中头文件包含关系复杂,开发人员为了省事起见,可能不会去一一钻研,直接包含一切想到的头文件,甚至有些产品干脆发布了一个god.h,其中包含了所有头文件,然后发布给各个项目组使用,这种只图一时省事的做法,导致整个系统的编译时间进一步恶化,并对后来人的维护造成了巨大的麻烦。 规则1.4 头文件应当自包含。 说明:简单的说,自包含就是任意一个头文件均可独立编译。如果一个文件包含某个头文件,还要包含另外一个头文件才能工作的话,就会增加交流障碍,给这个头文件的用户增添不必要的负担。 规则1.5 总是编写内部#include保护符(#define 保护)。 说明:多次包含一个头文件可以通过认真的设计来避免。如果不能做到这一点,就需要采取阻止头文件内容被包含多于一次的机制。 注: 没有在宏最前面加上 _ ,即使用 FILENAME_H代替 FILENAME_H ,是因为一般以 _ 和 __ 开头的标识符为系统保留或者标准库使用,在有些静态检查工具中,若全局可见的标识符以 _ 开头会给出告警。 定义包含保护符时,应该遵守如下规则: 1)保护符使用唯一名称; 2)不要在受保护部分的前后放置代码或者注释。 规则1.6 禁止在头文件中定义变量。 说明:在头文件中定义变量,将会由于头文件被其他.c文件包含而导致变量重复定义。 规则1.7 只能通过包含头文件的方式使用其他.c提供的接口,禁止在.c中通过extern的方式使用外部函数接口、变量。 说明:若a.c使用了b.c定义的foo()函数,则应当在b.h中声明extern int foo(int input);并在a.c中通过#include <b.h>来使用foo。禁止通过在a.c中直接写extern int foo(int input);来使用foo,后面这种写法容易在foo改变时可能导致声明和定义不一致。这一点我们因为图方便经常犯的。 规则1.8 禁止在[color=var(--weui-LINK)][url=]extern "C"[/url]中包含头文件。 说明:在extern "C"中包含头文件,会导致extern "C"嵌套,Visual Studio对extern "C"嵌套层次有限制,嵌套层次太多会编译错误。 建议1.1 一个模块通常包含多个.c文件,建议放在同一个目录下,目录名即为模块名。为方便外部使用者,建议每一个模块提供一个.h,文件名为目录名。 建议1.2 如果一个模块包含多个子模块,则建议每一个子模块提供一个对外的.h,文件名为子模块名。 建议1.3 头文件不要使用非习惯用法的扩展名,如.inc。 建议1.4 同一产品统一包含头文件排列方式。
|