假设我有一个标题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.h
和foo.cpp
是一个很好的实践吗?重点是:如果我阅读foo.cpp
,我怎么能理解MyClass来自哪里?我需要看一下foo.h
,但这会更难。
答案 0 :(得分:7)
我遵循的做法:
#include <string>
,则为std::string
)这种做法的另一种表述:在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文件来说更是一个问题,但我仍然是为了保持一致。