包括什么
What to #include?
我知道如果a.h
包括b.h
,我不声明任何从b.h
在我的头只包括a.h
是很好的做法。如果我要在我的头文件中声明b.h
中的任何内容,那么我应该包括a.h
和b.h
以使我的头文件自给自足。
在我的头我声明class A
从a.h
和class B
从b.h
。然而,class A
依赖于class B
,所以我总是把它们放在一起使用。我从不单独使用class B
和class A
。在这种情况下,它仍然有意义,包括a.h
和b.h
?
a.h
#include "b.h"
#include <queue>
class A
{
private:
std::queue<B> mFoo;
}
在我的实际代码中,我认为当我只包括我的事件系统,而不是一些对我来说似乎多余的包括时,它使我的意图更清晰。
应该始终包含直接依赖项:如果a直接依赖于b和c,即使b已经包含c, a也应该包含这两个。
明确你的依赖关系。您不应该依赖于其他模块已经依赖于您必须包含的模块的事实。你永远不知道依赖树将来会如何变化。
在这方面,隐式依赖会使你的代码脆弱。
为了确保你不会通过包含两次来重新定义某个内容,你可以在头文件中添加header guard:
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct foo {
int member;
};
#endif /* GRANDFATHER_H */
也可以用
#pragma once
但不是每个编译器都支持
这样,即使预处理器多次处理相同的include,它也不会重新包含代码。
我的规则:给定一些随机的头文件foo.h
,下面的代码应该编译干净,最好也能链接和运行:
#include "foo.h"
int main () {}
假设foo.h
不包含任何语法错误(即,源文件在您希望编译干净的上下文中包含它),但上述内容仍然无法编译。这几乎总是意味着foo.h
中缺少一些#include
指令。
这并没有告诉你是否真的需要foo.h
中包含的所有头文件。我有一个方便的小脚本来检查上面的内容。如果它通过了,它创建一个foo.h
的副本,并逐步注释出#include
指令,并查看foo.h
的修改版本是否通过了上述测试。任何通过的都表明存在可疑的多余的#include
指令。
问题是被认为是多余的#include
指令可能不是多余的。假设foo.h
定义了类Foo
,该类的数据成员类型分别为Bar
和Baz
(不是指针,是成员)。头foo.h
正确地包括bar.h
和baz.h
,因为这是定义这两个类的地方。假设bar.h
碰巧包含baz.h
。作为foo.h
的作者,我不在乎。我仍然应该包括这两个头在foo.h
,因为foo.h
有直接依赖于这两个其他的头。在这种情况下,我的脚本将抱怨可疑的多余头。这些抱怨是暗示,不是命令。
另一方面,修复foo.h
以使上面的简单测试程序编译干净是一项任务。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 警告处理为错误这里有什么问题
- 在用户类中包括PYBIND11嵌入式模块的正确方法(作为Singleton类的一部分)是什么?
- 在什么情况下我们需要包括<cassert>?
- 前向声明?,包括警卫?,或其他什么
- 我在 c++ 中的赋值重载运算符有什么问题?(包括详细信息)
- 我包括了“SDL_TTF.h”.我还应该对SDT真正类型的字体工作做些什么
- 为什么包括警卫对我没有影响?我是不是错过了什么
- 是什么导致TU被包括在汇编中
- 什么更好:包括字符串类或使用字符数组?
- 我需要添加什么到一个项目,包括库
- 包括"file.h"与有什么<file>区别?
- 我需要包括什么使用OpenClipboard()
- Eclipse CDT 无法构建 - 不确定出了什么问题(包括控制台)
- 打印类型包括装饰,模板元编程,constexpr,使用什么
- 在任何头文件中只定义一个类,而不包括包含此类的整个头文件的目的是什么?
- 在什么情况下我应该战斗深度#包括树
- 有什么理由让比较的形式仅为 <= 和 >=(不包括 =< 和 =>)?
- 包括在头或cpp -什么是首选的Qt
- 包括什么