Re: [問題] 關於C++ compiler的一些問題
※ 引述《kicksmile (aa)》之銘言:
: //class.h檔
: class A{
: public:
: void func();
: private:
: int x;
: };
: //class.cpp檔
: #include "class.h"
: void A::func()
: {
: x=x+1;
: }
: //main.cpp檔
: #include "class.h"
: int main(){
: A a1;
: a1.func();
: return 0;
: }
: 我想請教一下compiler在產生執行檔的過程中都在做些什麼
: 還是有什麼網站有教這些常識謝謝
你是讀什麼的呢?如果是資訊相關科系,有一門課叫做compiler,可以去聽聽看。
compiler主要把原始程式作剖析(parsing),檢查語彙(lexical),檢查語法(syntax)及
檢查語義(semantic),中間的運作過程,細節很多。你也可以去wikipedia找看看。
檢查完後,會替中間碼優化,最後再輸出對應的機械碼。
至於C Compiler的運作,主要是先作preprocessing(處理巨集代換),再作compile,產生
目的碼。有了目的碼後,再利用連結器把不同部份連結,產生執行檔。
: <compile的過程中>
: 1.因為class.cpp main.cpp都只include class.h
: 所以是不是main.cpp裡在compile的過程中看不到class.cpp裡的func計算過程?
compile的過程並不執行程式碼。每一個cpp都只是獨立編譯,再連結。你這句話語焉不詳
。就編譯器而言,它只看得到目前的原始檔,所以它不會管其它的檔案內怎麼寫。但,
就如同我之前講的,不參與計算。
: 2.那我在compile class.cpp時,compiler 是不是只是在做class.h 跟class.cpp的
: pattern 跟type (class裡的function argument, return type)檢查,然後產生class.obj?
: 相對的,compile main.cpp 也只是對main.cpp跟class.h做pattern跟type的檢查
: 然後產生main.obj?
對。
: 3.如果是的話,那compiler是在什麼時候才讓main.cpp裡的a1.func()去連結到
: class.cpp裡的func()計算內容?
事實上,它不會那麼做。一般會有這種錯覺,是因為IDE替你作了。一般會有個makefile
,就像個批次檔,會把每個原始檔編譯,各產生目的檔,再連結起來。如果你全部用手動
進行,就要一個一個下命令。
: 是在build solution的時候嗎?如果是的話,那是用什麼方法把他們連結起來的?
用連結器。
: 是在build的時候,遇到a1.func()的時候,去class.cpp(class.obj ? )裡找相對應的function,
: 把function寫進執行檔裡並將a1.func()指到那個function存在的位址嗎?
連結器會看看每個目的檔中,參照了哪個函式。並且確保大家的坑都有蘿剝插。
: 4.只是好奇,如果我在class外,寫了三個function(有兩個沒有用到), 雖然
: 沒用到應該刪掉或註解掉,但是如果我沒註解掉,
: 那我的執行檔裡會存三個還是一個function呢?
這樣的函數,一樣會存在。也許不同的compiler有不同的作法?
: 5.所以template跟inline function,如果存成兩個file class.h class.cpp
: build solution會有問題,是因為build的過程,main.obj裡的所用到的
: tmeplate function並沒有在compile的過程替換成所應該對應的type
: 導致main.obj在class.obj裡找不到對應的function?
是的,那表示你的instance無法被推導(induction)。template較為特殊,因為它必需
以原始碼型態存在於你的編譯標的中。若它被編譯後,才進行連結,那你的instance
就無法被推導了。
在c++ templates: the complete guide中有提及這些問題,並且衍生出原始碼是否應
該公開的討論。
考慮下列程式:
callee.cpp:
#include <cstdio>
#include "callee.hpp"
template <typename T>
void callee(T var){
printf("The size of argument is %d\n", sizeof(var));
}
callee.hpp
template <typename T>
void callee(T var);
caller.cpp
#include <cstdio>
#include "callee.hpp" //Notice this line!!!
int main(int argc, char *argv[]) {
callee(10);
callee("str");
return;
}
若是傳統的C或C++,則我標明的那行,不管是放callee.hpp,或是callee.cpp,都不會錯
但若是用了template,則一定要改成callee.cpp,否則會報錯,因為它在callee.obj中
找不到具callee(int)及callee(char *)兩原型的函數。所以一定要把callee.cpp給
caller.cpp引入,而不能只給obj檔,否則就無法推導。
: 那為什麼compiler會想把main.cpp裡的template function做替換
: 然後製做出main.obj
: 而不是
: 在build solution的時候再做替換,直接把替換過的function寫入執行檔?
: 有什麼壞處嗎?除了main.obj裡沒有相對應的function...
we dicussed above.
--
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 218.166.202.127
※ 編輯: ccbruce 來自: 218.166.202.127 (03/25 18:54)
※ 編輯: ccbruce 來自: 218.166.202.127 (03/25 19:03)
推
03/25 19:07, , 1F
03/25 19:07, 1F
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章