2

假设您正在创建一个包含多个 .cpp 文件(每个文件都包含成员函数的实现)的类,并且在 .h 文件中声明了类。此外,每个 .cpp 文件都通过 include 指令包含 .h 文件。

有人告诉我,如果您更改任何成员函数(.cpp 文件)的实现,则必须重新编译每个 .cpp 文件才能运行程序。也就是说,如果我有 5 个成员函数(每个都在 .cpp 文件中实现)并且我更改了 1 个 .cpp 文件的实现,我将不得不编译我更改的 1 个 .cpp 文件和我更改的 4 个其他 .cpp 文件没有为了正确运行我的程序而改变。

我的问题是,如果前面的陈述是真的,为什么陈述是真的?对这个概念的任何见解都会有所帮助。

4

3 回答 3

5

这是假的。如果一个特定的实现文件没有变化,它包含的头文件没有变化,环境或编译器选项没有变化,那么绝对不需要重新编译它。影响该文件编译的所有内容都没有改变。

事实上,您可以编译每个文件,甚至根本不需要任何其他文件。然后,您可以将所有编译文件链接在一起,而无需所有实现文件都在同一个地方。

于 2012-04-09T03:47:48.720 回答
3

该声明是错误的。事实上,make存在的全部原因(和类似的)是因为它是错误的——它们通过跟踪哪些源文件已更改并仅重新创建依赖于源文件的目标文件来最大限度地减少重建应用程序的时间/精力那已经改变了。最新的目标文件被简单地保留。

一旦所有目标文件都是最新的,它们就会链接在一起以生成最终的可执行文件(同样,这通常仅在/如果至少一个目标文件比当前可执行文件更新时执行)。

当然,它也可以make用于与编译和链接无关的工作,但这几乎可以肯定是它们最常见的用途,以及(至少大部分)它们被发明的原因(唯一明显的变化是它们最初主要用于 C 源代码而不是 C++,但在这方面两者几乎无法区分)。

两者之间唯一明显的区别是,当/如果您使用模板时,通常最终会将大量代码放入标题中。在这种情况下,更改标头会强制重新编译包含该标头的所有代码,这通常很多。使用 C 代码和/或非模板 C++ 代码,您将大部分代码放入源文件中,因此如果您更改代码的接口(通常会更改标头),则只需重新编译其他文件,但如果您在不更改接口的情况下限制对实现的更改,则只需重新编译该文件。

于 2012-04-09T04:09:31.860 回答
1

正如其他人所说,这种说法是错误的。然而,在修改源文件、源依赖和重新编译方面确实存在有趣的复杂性。不出所料,最有帮助的讨论是在 Herb Sutter 的一系列 Guru of the Week 帖子中给出的,他在其中讨论了依赖隔离和 Pimpl 成语:

编译防火墙

快速 Pimpl 成语

粉刺的喜悦

几乎每个人第一次看到这些东西时都觉得很深奥,但 Pimpl 成语在实践中却非常有用。

于 2012-04-09T05:27:25.583 回答