假设您正在创建一个包含多个.cpp文件的类(每个文件都包含成员函数的实现),并在.h文件中包含类'声明。此外,每个.cpp文件都通过include伪指令包含.h文件。
有人告诉我,如果更改任何成员函数(.cpp文件)的实现,则必须重新编译每个.cpp文件才能运行该程序。也就是说,如果我有5个成员函数(每个都在.cpp文件中实现)并且我改变了.cpp文件中的1个的实现,我将不得不编译我改变的1 .cpp文件和其他4个.cpp文件我为了正确运行我的程序没有改变。
我的问题是,如果前面的陈述是真的,为什么陈述是真的?对这个概念的任何见解都会有所帮助。
答案 0 :(得分:4)
这是假的。如果对特定实现文件没有更改,则不对其包含的头文件进行更改,并且不更改环境或编译器选项,则完全不需要重新编译它。影响该文件编译的所有内容都没有改变。
实际上,您可以编译每个文件,甚至根本不需要任何其他文件。然后,您可以将所有已编译的文件链接在一起,而不会将所有实现文件放在同一个位置。
答案 1 :(得分:3)
该陈述是错误的。实际上,存在make
(和类似)的全部原因是因为它是错误的 - 它们通过跟踪哪些源文件已更改并仅重新创建目标文件来最小化重建应用程序的时间/精力这取决于已更改的源文件。最新的目标文件只是保持不变。
一旦所有目标文件都是最新的,它们就会链接在一起产生最终的可执行文件(而且,这通常只在/当至少一个目标文件比当前可执行文件更新时才会完成)。 / p>
当然,也可以将make
用于与编译和链接无关的工作,但这几乎可以肯定是它们最常用的用途,以及(至少大部分)它们的用途发明了(唯一明显的变化是它们最初主要用于C源代码而不是C ++,但在这方面,这两者几乎无法区分)。
两者之间唯一明显的区别是,当您使用模板时,通常最终会将大量代码放入标题中。在这种情况下,更改标头会强制重新编译包含该标头的所有代码,这通常很多。使用C代码和/或非模板C ++代码,您将大部分代码放入源文件中,因此如果将 interface 更改为代码,则只需重新编译其他文件(通常会更改标题),但如果您在不更改界面的情况下限制对实现的更改,则只需要重新编译该文件。
答案 2 :(得分:1)
正如其他人所言,该陈述是错误的。但是,确实存在有关修改的源文件,源依赖项和重新编译的有趣复杂性。不出所料,最有帮助的讨论是在Herb Sutter的一系列本周大师的帖子中给出的,其中他讨论了依赖性隔离和Pimpl习语:
这些东西在他们第一次看到它时几乎对所有人来说都是深奥的,但是Pimpl成语在实践中变得非常有用
。