2017-05-21 32 views
0

爲什麼在預處理步驟中,主文件中的#include僅被替換爲相關頭文件的內容(而不是函數定義(.cpp文件))?源代碼構建混淆(預處理和鏈接)

我認爲在這一步它應該首先進入頭文件,並用相關的.cpp文件的內容替換#includes,然後回去替換主文件中的#includes與一切,從而否定任何鏈接(一個巨大的文件與一切)的需要。爲什麼不會發生這種情況?

+2

因爲你每次都要編譯許多次代碼。每次都會重新編譯一個沒有改變的CPP文件。使用預編譯的庫加快編譯速度是不可能的。 – user4581301

+1

另外,正常的方法可以讓你使用你甚至沒有源代碼的函數。 –

+0

「...它們的相關.cpp文件」。在C++語言中, 中沒有這樣的關聯。你可以調用一個頭文件'iostream'(就像 C++標準庫所做的那樣),並且在任意數量的源文件中定義被聲明爲 的東西,稱爲任何你喜歡的東西。 –

回答

0

爲什麼在預處理步驟中,主文件中的#include僅被替換爲相關頭文件的內容(而不是函數定義(.cpp文件))?

簡而言之,頭文件是您告訴預處理器的唯一文件。它不能假定源文件的名稱,因爲對於任何給定的頭文件可能有許多源文件。你可能會想:「嘿,我爲什麼不只是包括的源文件?」我在這裏告訴你不!壞!另外,誰說你可以首先訪問源文件?

編譯器知道並編譯所有源文件的唯一方法是讓編譯器傳遞每個源文件,讓它們編譯成對象,並將這些對象鏈接到一個庫或可執行文件中。

0

compiling and linking之間有很大的區別:

預處理器,預編譯時和編譯時間:

預處理器檢查#符號,並與相關的內容如替代它:

#include <iostream> // the content will be replaced here and this line will be removed 

所以iostream的內容將被添加到上面。

EG2:

#define PI 3.14 // wherever PI is used in your source file the macro will be expanded replacing each PI with the constant value 3.14 

編譯器僅檢查syntax errors,函數的原型... and doesn't care about the body of functions, resulting in an的obj file`。

鏈接時:

鏈接器鏈接這些obj files有關庫,在這非常時期functions called必須有一個定義;沒有定義將在鏈接時錯誤中發佈。

0

爲什麼它不會發生這種情況?

歷史和經驗的程序員的期望,以及他們與大項目的經驗(見最後陳述,下同)


我認爲,在這個步驟中,應該首先進入頭 文件,並與他們相關的 .cpp文件的內容替換#包括有...

如果ACCE對於使用C++進行編碼的工作,貴公司將爲您提供編碼標準,詳細說明您將要遵循的指導方針或規則,或者在您偏離它們時面臨捍衛您的選擇的問題。

您現在可能需要一些時間才能查看可用的編碼標準。例如,嘗試學習Google C++風格指南(我不特別喜歡或不喜歡這個,它只是很容易記住)。一個簡單的谷歌搜索也可以找到幾種編碼標準。添加'爲什麼符合編碼標準?'到您的搜索可能會提供一些信息。


否定任何鏈接的需求(一切一個巨大的文件)。

注意:這種方法不能消除與編譯器工具或第三方提供的庫的鏈接。我經常使用-lrt,-pthread和一些時間-lncurses,-lgmp,-lgmpxx等。

現在,作爲一個實驗,您可以手動實現巨型文件方法(我經常爲我做的較小的試用和私人工具的開發)。

試想一下:

如果main.cc有:

#include "./Foo.hh" // << note .hh file 

int main(int argc, char* argv[]) 
{ 
    Foo foo(argc, argv); 

    foo.show(); 
... 

和Foo.cc具有

#include "./Foo.hh" // << note .hh file 

// Foo implementation 

這個普通模式(不,不是模式書模式),並且會要求你將Foo.o和main連接在一起,這對於小構建來說足夠小,但還有更多的事情要做。

的「small'岬允許您使用的#include創建你的‘一切’容易一個巨大的文件:

變化主要以

#include "./Foo.cc" // << note .cc also pulls in .hh 
         // (prepare for blow back on this idea)  

int main(int argc, char* argv[]) 
{ 
    Foo foo(argc, argv); 

    foo.show(); 
... 

編譯器看到所有的代碼在一個編制單位。沒有鏈接本地.o的需要(但仍然庫鏈接)。


請注意,我不建議這樣做。爲什麼?

可能主要原因是我的很多工具都有100個對象(即100個.cc文件)。那個單一的「巨人」檔案可能相當龐大。

對於大多數開發流失(即早期錯誤修復),只有一個或兩個.cc文件獲取更改。重新編譯所有源代碼可能會浪費大量時間和編譯器的時間。

替代方案是什麼經驗的開發人員已經瞭解到:

A)編制的.cc的小得多的數量已經改變了(也許是一個或兩個),

B),然後與連接它們?沒有改變的其他.o's的100年代更快地構建。

您的工作效率的一個關鍵是最大限度地減少編輯 - 編譯 - 調試時間。 A和B以及一個好的編輯器對這個迭代很重要。