您可以构造一个 C++ 程序,以便(几乎)所有代码都驻留在头文件中。它本质上看起来像一个 C# 或 Java 程序。但是,您确实需要至少一个 .cpp
文件来在编译时拉入所有头文件。现在我知道有些人绝对会讨厌这个想法。但我没有发现这样做有任何令人信服的缺点。我可以列出一些优点:
[1] 更快的编译时间。所有头文件只被解析一次,因为只有一个 .cpp 文件。此外,一个头文件不能包含多次,否则会导致构建中断。使用替代方法时,还有其他方法可以实现更快的编译,但这很简单。
[2] 它通过使它们绝对清晰来避免循环依赖。如果 ClassA.h
中的 ClassA
对 ClassB.h
中的 ClassB
有循环依赖,我必须放一个前向引用&它突出。 (请注意,这与编译器自动解析循环依赖关系的 C# 和 Java 不同。这鼓励了 IMO 的不良编码实践)。同样,如果您的代码位于 .cpp
文件中,您可以避免循环依赖,但在实际项目中,.cpp
文件往往会包含随机 header ,直到您可以'不知道谁依赖谁。
你的想法?
最佳答案
原因 [1] 更快的编译时间
不在我的项目中:源文件 (CPP) 仅包含他们需要的 header (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. */ }
解决问题的一个好方法是将此源分解为每个类至少一个源/ header (以类似于 Java 的方式,但每个类有一个源和一个 header ):
// 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. */ }
因此,没有依赖性问题,并且编译时间仍然很快。
我错过了什么吗?
在从事“现实世界”项目时
in a real-world project, cpp files tend to include random headers until you can't figure out who depends on whom
当然。但是,如果您有时间重新组织这些文件以构建您的“一个 CPP”解决方案,那么您就有时间清理这些 header 。我的标题规则是:
- 分解标题以使其尽可能模块化
- 永远不要包含你不需要的标题
- 如果你需要一个符号,前向声明它
- 仅当上述失败时,才包含标题
无论如何,所有的 header 必须是自给自足的,这意味着:
- 一个 header 包括所有需要的 header (并且只有需要的 header - 见上文)
- 必须编译包含一个 header 的空 CPP 文件,而无需包含其他任何内容
这将消除排序问题和循环依赖。
编译时间有问题吗?那么……
如果编译时间真的是一个问题,我会考虑:
- 使用预编译的头文件(这对 STL 和 BOOST 非常有用)
- 通过 PImpl 习语减少耦合,如 http://en.wikipedia.org/wiki/Opaque_pointer 中所述
- 使用网络共享编译
结论
您所做的并不是将所有内容都放在标题中。
您基本上是将所有文件包含在一个且只有一个最终源中。
也许您在完整项目编译方面获胜。
但是当编译一个小的改变时,你总是会输的。
编码时,我知道我经常编译小的更改(如果只是让编译器验证我的代码),然后最后一次,做一个完整的项目更改。
如果我的项目按照你的方式组织,我会浪费很多时间。
关于c++ - 将所有代码放在 C++ 头文件中的优点和缺点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/193864/