2012-04-09 106 views
2

假设您正在创建一个包含多个.cpp文件(每个都包含成员函数的实现)的类,并在.h文件中包含该类的声明。另外,每个.cpp文件都通过include指令包含.h文件。C++中的单独编译

我被告知,如果您更改任何成员函数(.cpp文件)的实现,您将不得不重新编译每个.cpp文件以运行该程序。也就是说,如果我有5个成员函数(每个函数都在.cpp文件中实现),并且我更改了.cpp文件中的一个的实现,我将不得不编译1个.cpp文件,并更改了另外4个.cpp文件没有改变为了正确运行我的程序。

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

+0

查看与基类有关的[类似问题](http://stackoverflow.com/questions/9188101/recompile-after-base-class-change/9188135)。 – 2012-09-26 01:59:40

回答

4

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

事实上,你甚至可以编译每个文件,甚至没有其他任何文件。然后,您可以将所有已编译的文件链接在一起,而不必将所有实现文件放在同一个位置。

+0

头文件也是C++文件...使用术语“实现”文件,甚至是常见扩展名列表ala .cc/.cpp,不太令人困惑.... – 2012-04-09 06:48:05

+1

@TonyDelroy谢谢。完成。 – 2012-04-09 06:51:12

3

该声明是错误的。实际上,make(以及类似的)存在的全部原因是因为它是错误的 - 它们通过跟踪哪些源文件已更改来重建应用程序的时间/工作量最小化,并且仅重新创建依赖于源的对象文件已更改的文件。最新的对象文件只是单独保留。一旦所有的目标文件都是最新的,它们被链接在一起以产生最终的可执行文件(并且,通常只在/如果至少有一个目标文件比当前的可执行文件更新时才这样做)。

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

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

+0

对于一个好的答案+1,虽然私人和受保护的成员,内联函数等都是头文件中经常出现的“实现”的其他例子。 pmcs的答案列出了一些有关那些链接.... – 2012-04-09 06:45:43

1

正如其他人所说,这种说法是错误的。但是,修改后的源文件,源依赖关系和重新编译确实存在一些有趣的复杂性。

Compilation Firewalls

The Fast Pimpl Idiom

The Joy of Pimpls:这方面最有帮助的讨论,勿庸置疑,从香草萨特周的帖子,他在其中讨论的依赖隔离和PIMPL方法的一系列大师的给

这东西似乎深奥到几乎所有人第一次看到它,但皮姆普成语竟然是惊人在实践中有用。