簡體   English   中英

為什么我們需要在編譯期間包含C或CPP聲明文件而不是像iostream這樣的默認庫?

[英]Why do we need to include the C or CPP declaration files during compilation and not the default libraries like iostream?

如果需要使用我們自己的帶有聲明的頭文件和帶有定義的cpp文件來編譯CCPP程序,我們需要在編譯命令中包含帶有定義的cpp文件(請參閱此答案 )。 但是,當我們編寫#include <iostream> ,我們不會在編譯語句中包含iostream.cpp ,如g++ main.cpp iostream.cpp -o main

如果我們寫我們的報關文件,例如hello.hpp帶班宣言和hello.cpp與定義,我們需要使用編譯它g++ main.cpp hello.cpp -o main包括后hello.hpp在頭main.cpp文件。 為什么是這樣?

編輯 :我們可以模仿我們的自定義頭文件和cpp文件的標准模板庫的行為,這樣我們所要做的就是包含頭文件並自動編譯聲明嗎? 如果是,那怎么樣? 如果不是,為什么不呢?

標准庫正在隱式鏈接。 所以

g++ main.cpp -o main

是真的

g++ main.cpp -o main -lstdc++ -lc

其中libstdc++是c ++標准庫, libc是c標准庫。 其他庫需要明確鏈接(例如libm )。

如果您將編譯和鏈接步驟分開,這將變得更加清晰:

g++ -c main.cpp -o main.o
g++ -c other.cpp -o other.o
g++ main.o other.o /usr/lib/libstdc++.a /usr/lib/libc.a -o main

這里我們將main()函數定義和其他定義( other.cpp )編譯成目標文件,並將它們與標准庫中現有的編譯函數/類/變量定義相結合。

有關如何將定義文件( .c.cpp )轉換為庫的詳細信息,請參閱共享庫創建靜態庫創建的 TLDP頁面。

首先,檢查在這篇文章中包含<filename>"filename"之間的區別:

對於#include“filename”,預處理器在與包含該指令的文件相同的目錄中進行搜索。 此方法通常用於包括程序員定義的頭文件。

對於#include <filename>,預處理器以依賴於實現的方式搜索,通常在編譯器/ IDE預先指定的搜索目錄中搜索。 此方法通常用於包括標准庫頭文件

您包含文件的事實並不意味着您正在編譯文件。 事實上,通過包含你正在解決包含文件的語法引用,如類聲明(在C ++中),常見變量,結構,枚舉和函數調用。 這將避免代碼獲取未引用的對象錯誤,從而破壞編譯過程。

使用這些引用編譯代碼並不意味着編譯原始引用的代碼。 舉個例子:

mycode.cpp包含myclass.hpp ,如下所示:

#include "myclass.hpp"

如果引用正確,您可以使用以下命令編譯它:

g++ mycode.cpp 

你將有一個mycode.cpp (一個名為mycode.o的目標文件)的編譯代碼,但不是myclass的編譯代碼。 mycode.cpp編譯正確,因為它有對myclass對象/函數/等的引用,但這並不意味着myclass被編譯(你還沒有一個對象文件myclass.o )。

如果你鏈接編輯mycode.cpp ,將會有幾個缺少的引用,因為沒有myclass編譯代碼。

如果您選擇:

g++ mycode.cpp myclass.cpp 

它將為mycode.omyclass.o生成目標文件,以后可以將它們鏈接在一起。

對於STL庫,您只需要引用,因為它們已經編譯並且可用於所謂的標准庫(已經為您編譯的一組對象.o文件)。 如果您正確地告訴他這樣做,那么liker會自動聯系在一起。

我建議你通過compilation -> object files -> link editing -> executable file進程來理解這些步驟,這只發生在編譯語言中。

您需要了解編譯器讀取輸入文件,然后預處理它們,預處理器替換所有#include語句,以便編譯器本身永遠不會看到它們。 就真正的編譯器而言,沒有#include語句。 然后,編譯器將源語言轉換為機器代碼。 編譯器為每個輸入(c或cpp)文件編寫一個目標文件。 目標文件中的機器碼不能直接執行; 它必須與其他代碼鏈接。

最初,程序員會將程序與已經編譯成目標文件庫的其他目標文件鏈接起來。 多個目標文件靜態鏈接在一起以生成可執行文件,並且可以對許多可執行文件執行此操作。 換句話說,許多目標文件中的每一個都可能存在多次,對於許多可執行文件中的每一個都存在一次。 這意味着當某些內容發生變化時,有時必須再次鏈接許多使用相同目標文件的程序。 后來的程序員了解到它有助於動態鏈接到目標文件,這就是動態鏈接庫。

編譯程序時,編譯器包含鏈接器鏈接到其他庫的指令,主要是“C運行時”(CRT)。 鏈接可以是靜態鏈接或動態鏈接。 此外,標頭提供有關CRT的信息。 大多數標准庫(std命名空間)實際上都在標題中,例如在“iostream”中,並使用您的程序進行編譯。 標題中沒有的任何內容都在某個CRT庫中。

因此,iostream.cpp的等價物可能在您自己的程序中,例如main.cpp,或者已經編譯過,並且位於與您的程序鏈接的CRT庫中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM