头文件绝对不应包含哪些内容?
例如,如果我正在使用具有许多常量的已记录的行业标准格式,那么在头文件中定义它们(如果我正在为该格式编写解析器)是否是一种好习惯?
头文件应包含哪些功能?
什么功能不应该?
头文件绝对不应包含哪些内容?
例如,如果我正在使用具有许多常量的已记录的行业标准格式,那么在头文件中定义它们(如果我正在为该格式编写解析器)是否是一种好习惯?
头文件应包含哪些功能?
什么功能不应该?
Answers:
标题中要放什么:
#include
当标头包含在某些源文件中时,使标头可编译所需的最少指令集。标头中不包含的内容:
#include
指令。这些无用的内容会导致不需要重新编译的内容重新编译,并且有时可以重新编译,从而导致系统无法编译。不要#include
一个文件中的一个标题,如果标题本身并不需要其他的头文件。#include
,可能更改或太大的函数的内联定义。这些内联函数应该几乎没有扇出,如果确实有扇出,则应将其本地化为标头中定义的内容。最小的#include
陈述集是什么?
事实证明这是一个不平凡的问题。TL; DR定义:头文件必须包括直接定义直接使用的每种类型或直接声明所涉及的头文件中使用的每个功能的头文件,但不得包含任何其他内容。指针或C ++引用类型不适合直接使用;前向引用是首选。
有一个免费#include
指令的位置,这是在自动测试中。对于软件包中的每个头文件,我都会自动生成然后编译以下内容:
#include "path/to/random/header_under_test"
int main () { return 0; }
编译应该干净(即没有任何警告或错误)。关于不完整类型或未知类型的警告或错误意味着被测试的头文件缺少某些#include
指令和/或缺少前向声明。请注意:仅仅通过测试并不意味着#include
指令集就足够了,更不用说最少了。
除了已经说过的。
H文件应始终包含:
H文件绝对不能包含:
static
。(我还要说,从来没有任何理由在任何地方使用非常量全局/外部变量,但这是另一篇文章的讨论。)
我可能永远不会说“永不”,但是在解析时生成数据和代码的语句不应放在.h文件中。
宏,内联函数和模板可能看起来像数据或代码,但它们不会在解析时生成代码,而是在使用时生成代码。这些项目通常需要在多个.c或.cpp中使用,因此它们属于.h。
在我看来,头文件应该具有对应于.c或.cpp的最小实际接口。接口可以包括#defines,class,typedef,struct定义,函数原型,以及不太受欢迎的全局变量extern定义。但是,如果仅在一个源文件中使用声明,则可能应将其从.h中排除,而应包含在源文件中。
有些人可能不同意,但是我个人对.h文件的标准是它们#include所有其他需要编译的.h文件。在某些情况下,这可能是很多文件,因此我们有一些有效的方法来减少外部依赖性,例如对类的前向声明,这些类使我们可以使用指向类对象的指针,而不必包括包含文件的大树。
头文件应具有以下组织:
头文件不应包含对象定义,只能包含类型定义和对象声明。
在解析时生成数据和代码的语句不应位于.h
文件中。就我的观点而言,头文件应仅具有对应于.c
或的最小实际接口.cpp
。