原因 [1] 更快的编译时间
不在我的项目中:源文件 (CPP) 仅包含他们需要的标头 (HPP)。因此,当我因为一个微小的变化而只需要重新编译一个 CPP 时,我有十倍于相同数量的未重新编译的文件。
也许您应该将项目分解为更合乎逻辑的源/标题:A 类实现的修改不需要重新编译 B、C、D、E 类等的实现。
原因[2] 避免循环依赖
代码中的循环依赖?
抱歉,但我还没有遇到真正的问题:假设 A 依赖于 B,B 依赖于 A:
struct A
{
B * b ;
void doSomethingWithB() ;
} ;
struct B
{
A * a ;
void doSomethingWithA() ;
} ;
void A::doSomethingWithB() { /* etc. */ }
void B::doSomethingWithA() { /* etc. */ }
解决该问题的一个好方法是将此源分解为每个类至少一个源/标头(以类似于 Java 的方式,但每个类具有一个源和一个标头):
// A.hpp
struct B ;
struct A
{
B * b ;
void doSomethingWithB() ;
} ;
.
// B.hpp
struct A ;
struct B
{
A * a ;
void doSomethingWithA() ;
} ;
.
// A.cpp
#include "A.hpp"
#include "B.hpp"
void A::doSomethingWithB() { /* etc. */ }
.
// B.cpp
#include "B.hpp"
#include "A.hpp"
void B::doSomethingWithA() { /* etc. */ }
因此,没有依赖性问题,并且编译时间仍然很快。
我错过了什么?
在从事“现实世界”项目时
在实际项目中,cpp 文件往往会包含随机标题,直到您无法弄清楚谁依赖于谁
当然。但是,如果您有时间重新组织这些文件以构建您的“一个 CPP”解决方案,那么您就有时间清理这些标头。我的标题规则是:
- 分解标题以使它们尽可能模块化
- 永远不要包含你不需要的标题
- 如果你需要一个符号,前向声明它
- 仅当上述失败时,才包含标头
无论如何,所有标题都必须是自给自足的,这意味着:
- 标头包括所有需要的标头(并且只有需要的标头 - 见上文)
- 必须编译包含一个标头的空 CPP 文件,而无需包含其他任何内容
这将消除排序问题和循环依赖。
编译时间有问题吗?然后...
如果编译时间真的是一个问题,我会考虑:
结论
您所做的并不是将所有内容都放在标题中。
您基本上是将所有文件包含在一个且只有一个最终源中。
也许您在完整项目编译方面获胜。
但是当编译一个小的变化时,你总是会输。
编码时,我知道我经常编译小的更改(如果只是让编译器验证我的代码),然后最后一次,做一个完整的项目更改。
如果我的项目按照你的方式组织,我会浪费很多时间。