2012-04-09 88 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方法的一系列大師的給

這東西似乎深奧到幾乎所有人第一次看到它,但皮姆普成語竟然是驚人在實踐中有用。