在实现中重新包含头

时间:2010-12-11 12:48:59

标签: c++ header

假设我有一个标题foo.h,如下所示:

#ifndef FOO_H
#define FOO_H
#include <string>
#include "non_standard_class.h"

std::string foo(MyClass a);
...
#endif

,实施foo.cpp将是

#include <vector>

#include "foo.h"

std::string foo(MyClass a)
{
   std::vector<int> x;
   MyClass b;
   ...
}

<string>中重新加入non_standard_class.hfoo.cpp是一个很好的实践吗?重点是:如果我阅读foo.cpp,我怎么能理解MyClass来自哪里?我需要看一下foo.h,但这会更难。

3 个答案:

答案 0 :(得分:7)

我遵循的做法:

  • foo.h应该直接包含其源代码所需的所有头文件(如果foo.h中有#include <string>,则为std::string
  • foo.cpp应该直接包含foo.h以及它自己的源代码所需的所有其他头文件,除了那些已经直接包含在foo.h中的文件。

这种做法的另一种表述:在foo。*中,只包含源代码所需的那些头文件。如果只有foo.cpp需要一个头(但不是foo.h),那么请从foo.cpp中包含它,否则从foo.h中包含它。

所以,在你的情况下,我不会在foo.cpp中#include <string>,因为它已经被foo.h包含了。

我们假设string执行#include <vector>,而foo.h包含std::vector。在这种情况下,我在foo.h中#include <vector>,因为它的源代码需要它 - 而且string已经包含它并不重要。

答案 1 :(得分:2)

我个人遵循(可疑的)最小包含练习:我只包括编译工作所需的内容。

人们告诉得到一个更好的编译器/机器让我发笑,在某种程度上,我每天工作的项目是在大约8分钟(从零开始)在四核上编译的(大约在我之前1小时)废弃了依赖关系)我觉得太长了。我当然不希望任何改变导致整个事情重新编译,因此我对任何包含都很谨慎。

在开发过程中,我总觉得编译时间浪费时间。有点可能允许休息,但是当你想要现在测试一些东西时,等待该死的东西最终做好准备是唯一令人沮丧的(特别是如果它在测试时只是在你的手中吹,你意识到你将不得不修改它再次重新编译再次)。

包括两次的东西似乎是一个好方法,当标题不再需要时,忘记从源中删除包含(对于前向声明的欢呼),我不明白这一点。

答案 2 :(得分:1)

我想说的是,因为否则你的foo.cpp依赖于可能会改变的foo.h的细节。显然这对于​​不受你控制的其他.h文件来说更是一个问题,但我仍然是为了保持一致。