我是否在头文件中使用标准库预处理器包含相应的实现文件是否重要?

时间:2012-08-14 11:29:26

标签: c++

如果我有一个项目

main .cpp 
Knife .h and .cpp
Cucumber .h and .cpp 

我想在Cucumber中使用Knife的成员,我是否使用以下内容是否重要:

#include "Knife.h"
#include <iostream>
using namespace std;

在Cucumber.h或Cucumber.cpp中(假设Cucumber.cpp已经包含了Cucumber.h)?

4 个答案:

答案 0 :(得分:3)

我的建议是尽量减少头文件中包含的文件数量。 所以,如果我有选择,我更愿意包含在源文件中。

修改头文件时,必须重新编译包含此头文件的所有文件。

因此,如果cucumber.h包含knife.hmain.cpp包含cucumber.h,并且您修改了knife.h,则会重新编译所有文件({{1 }},cucumber.cppknife.cpp)。

如果main.cpp包含cucumber.cppknife.h包含main.cpp,并且您修改了cucumber.h,则只会knife.hcucumber.cpp重新编译,因此缩短了编译时间。

如果你需要在黄瓜中使用刀,你可以这样做:

knife.cpp

这个“技巧”被称为“前向声明”。这是C ++开发人员众所周知的技巧,他们希望尽量缩短编译时间。

答案 1 :(得分:2)

是的,您应该将其放在.cpp文件中。

你会有更快的构建,更少的依赖,更少的工件和噪音 - 在iostream的情况下,GCC声明:

// For construction of filebuffers for cout, cin, cerr, clog et. al.
static ios_base::Init __ioinit;
命名空间std内的

。如果许多文件包含Knife.h,则该声明将产生大量(冗余)静态数据,这些数据必须在启动时构建。所以有很多胜利,唯一的损失就是你必须明确地包含你真正需要的文件 - 你需要的每个地方(在某些方面这也是一件非常好的事情)。

答案 2 :(得分:1)

我所看到的建议是仅包含给定源文件所需的最小值,并尽可能多地保留标题。在编译时,它可能会减少依赖性。

需要注意的另一件事是您的命名空间用法。你肯定要小心在标题中有这样的东西。它可能会更改您未计划的文件中的命名空间使用情况。

答案 3 :(得分:1)

作为一般规则,尝试将您的包含添加到实现文件而不是标题中,原因如下:

  • 减少潜在的不必要的包含,并将其保留在需要的地方。
  • 缩短编译时间(在某些情况下,我已经看到了。)避免暴露实现细节。
  • 降低出现循环依赖的风险。
  • 避免将标头的用户锁定为必须间接包含他们可能不需要/不需要的文件。

如果您只在标题中通过指针或引用引用类,则不必包含适当的标题;一个类声明就足够了。

可能还有其他一些原因 - 上述可能是最重要/最明显的原因。