是對嗎?
號
您需要了解函數的聲明和函數定義,編譯之間的差異,鏈接和執行,以及非虛擬和虛擬功能之間的差異之間的差異。
函數聲明
這是一個函數聲明:void max(void);
。它並沒有告訴編譯器關於函數的功能。它所做的是告訴編譯器如何調用該函數以及如何解釋結果。當編譯器編譯某個函數的主體時,將其稱爲函數A,編譯器不需要知道其他函數做了什麼。它需要知道的是如何處理函數A調用的函數。編譯器可能會生成彙編中的代碼或與您的C++函數調用相對應的某種中間語言。或者它可能會拒絕你的C++代碼,因爲你的代碼沒有意義。
確定您的代碼是否有意義是這些函數聲明的另一個關鍵目的。這在C++中特別重要,其中多個函數可以具有相同的名稱。如果不知道這些函數,編譯器如何知道函數調用哪個函數?當您的C++代碼調用某個函數時,編譯器必須找到其中一個函數聲明的最佳匹配(可能涉及類型轉換)。如果編譯器根本找不到匹配,或者找到多個匹配,但無法將其中一個匹配爲最佳匹配,那麼您的代碼沒有意義。
當編譯器確實找到最佳匹配,將所生成的代碼將在一個未定義的外部參照該函數的調用的形式。函數所在的位置不是編譯器的工作。
函數定義
這void max(void)
是一個函數聲明。相應的void max() {...}
是該函數的定義。當編譯器正在處理void max() {...}
時,它不必擔心其他函數調用它。它只需要擔心處理void max() {...}
。此函數的主體變成彙編或中間語言代碼,插入到某個編譯的目標文件中。編譯器將這個生成的代碼的入口點地址標記爲這樣。
編制與聯
到目前爲止,我已經談到了編譯器做什麼。它會生成與您的C++代碼相對應的低級代碼塊。由於這些外部引用,生成的代碼尚未準備好進入黃金時段。解決那些未定義的外部引用是鏈接器的工作。鏈接器是從多個目標文件和多個庫構建可執行文件的。它會跟蹤它將這些代碼塊放在可執行文件中的位置。那些未定義的外部引用呢?如果鏈接器已經將該引用放置在可執行文件中,則鏈接器只是填充該引用的佔位符。如果鏈接器沒有遇到該引用的定義,它會將引用和佔位符放到仍然未解析的引用的列表中。每當鏈接器向可執行文件添加一段代碼時,它都會檢查該列表以查看它是否可以修復任何尚未解析的引用。最後,您要麼解決了所有參考,要麼您仍然會有一些未完成的參考。後者是一個錯誤。前者意味着你有一個可執行文件。
執行
當你的代碼運行時,這些函數調用實際上只是一些堆棧管理各地的機器語言等同邪goto
聲明的包裹。沒有檢查你的函數聲明;這些代碼在執行時根本不存在。返回?那也是goto
。
非虛擬對虛擬函數
我上面說涉及非虛函數。運行時調度確實發生在虛擬功能上。運行時調度與檢查函數聲明無關。這些虛擬功能可能是另一個問題的問題。
最後一件事:
走出using namespace std;
認爲它是類似於吸菸的習慣。這是一個壞習慣。
您是否在詢問計算機在編譯期間或運行期間的功能? –
它可能會徹底擺脫所有功能的痕跡。 – chris
我在運行期間詢問,哪些東西(簽名,調用和定義)會使計算機看起來第一個和第二個... –