什么#include?

时间:2014-03-16 15:39:45

标签: c++ include

我理解,如果a.h包含b.h,并且我没有在我的标题中b.h声明任何内容,仅包括a.h,这是一种很好的做法。如果我要在我的标题中声明b.h中的任何内容,那么我应该同时包含a.hb.h以使我的标题自给自足。

在我的标题中,我确实声明class A中的a.hclass B中的b.h。但是,class A取决于class B,所以我总是一起使用它们。我从不使用class B独立于class A。在这种情况下,包含a.hb.h是否仍然有意义?

A.H

#include "b.h"
#include <queue>

class A
{

private:
   std::queue<B> mFoo;
}

在我的实际代码中,我认为当我仅包括我的事件系统时,我的意图更清晰,而不是一些对我来说似乎多余的包含。

2 个答案:

答案 0 :(得分:0)

您应始终包含直接依赖关系:如果 a 直接取决于 b c ,即使 b 已包含 c a 应包括两者。你永远不知道依赖树将来会如何变化。

为了确保您不会通过将其包含两次来重新定义某些内容,您可以将header guard放在头文件中:

#ifndef GRANDFATHER_H
#define GRANDFATHER_H

struct foo {
    int member;
};

#endif /* GRANDFATHER_H */

(维基页面的代码)

您也可以使用

#pragma once

但并非每个IDE都有它。 这样,即使预处理器同步包含多次,它也不会复制代码。

答案 1 :(得分:0)

我的规则:给定一些随机标题foo.h,以下内容应该编译干净,最好是链接和运行:

#include "foo.h"
int main () {}

假设foo.h不包含任何语法错误(即,在您打算编译干净的上下文中包含它的源文件),但上述内容仍然无法编译。这几乎总是意味着#include中有一些缺少foo.h指令。

这并不能告诉您foo.h中是否真正需要所有标头。我有一个方便的小脚本来检查上面的内容。如果它通过,它会创建foo.h的副本并逐步注释掉#include指令,并查看foo.h的那些修改版本是否通过了上述测试。任何通过的都表示怀疑是多余的#include指令。

问题是被认为是多余的#include指令可能不是多余的。假设foo.h定义了类Foo,它具有类型为BarBaz的数据成员(不是指针,成员)。标头foo.h正确包含bar.hbaz.h,因为这是定义这两个类的位置。假设bar.h恰好包含baz.h。作为foo.h的作者,我不在乎。我仍然应该在foo.h中包含这两个标头,因为foo.h对这两个标头都有直接依赖关系。在这种情况下,我的脚本会抱怨可疑的多余标题。这些投诉是暗示,而非强制性。

另一方面,修复foo.h以便我上面的简单测试程序编译清洁是一项任务。