c++中的型別查詢過程相對簡單,基本上就是名字查詢,這裡不再介紹。
對於 .cpp 檔案中呼叫的乙個函式 ( 或成員函式 ), 編譯器主要做了下面三件事情 :
1 名字查詢 . 先在所在編譯單元中可見名字實體中進行名字查詢 .(1) 類成員函式優先 ( 物件所在的類 -> 基類 ). 一 經找到就停止查詢 . (2 )如果沒有 ,在相應的名字空間中做進一步的搜尋 ; (3) 如果還沒有 , 會根據函式引數所在的名字空間中查詢 (keoning 查詢 ).
2 過載決議 . 根據所找到的名字進行過載決議 , 根據引數最匹配原則選擇相應的函式 .
3 可訪問性檢查 . 用以確定被選中的函式是否可被呼叫 .
說明 :
1) 根據第一條 , 顯然 , 如果型別想和非成員函式一起工作 , 那麼它們應該放在同乙個名字空間中 . 比如 , 一般型別的過載運算子和引數型別放在同乙個標頭檔案中/或者同乙個名字空間下 .
2) 函式特化模板不參與過載決議 , 因此 , 如果想運用某個函式的特化 , 最好的方法是過載該函式 , 在實現中採用該特化來工作 .
3) 過載決議發生在可訪問性檢查之前 . 因此 , 如果私有函式不幸參與了過載 , 並且被選中 , 最終也會出現無法訪問的編譯提示 . 這常常隱含二義性 , 這樣的設計本身也不合理 . 換句話說 , 私有引數 , 在名字查詢和過載時並非 是 」 私有的 」.
以 c.twice( 21 )的函式呼叫為例:
a) 名字查詢:編譯器會首先尋找乙個至少包含乙個名字為 twice 的實體作用域(類,檔案,或者名字空間),並將候選函式放入候選實體列 表。例子中,編譯器首先從物件 c 所在類實體中進行查詢,找到就停止;如果沒找到就會依次在其基類和外圍的名字空間中查詢,直到找到乙個至少含有乙個候 選函式的作用域。兩點需要注意: 1) 只要找到乙個實體就停止查詢,所以並非所有的同名函式都會被考慮; 2) 引數所在名字空間也屬於查詢範圍 (keoning 準則) 。
b) 過載決議:從所找到的候選過載函式列表中選出唯一最佳匹配 。如不唯一,就存在二義性。注意: 1) 這是基於名字查詢結果的; 2) 特化的模板函式不參與過載。
c) 可訪問性檢查:確定所選出的函式是否可訪問。這是最後一步,晚於過載決議。
文章中的規則非常重要,理解後,很多c++的編譯問題就自然解決了。後面將會有進一步的文章來介紹:如何確定c++每個編譯單元(cpp檔案) 中的可見名字(與名字查詢相關);keoning查詢詳解; 過載 (overload) 和虛函式的重實現 (override).
C 編譯器的函式編譯流程
c 中的型別查詢過程相對簡單,基本上就是名字查詢,這裡不再介紹。對於 cpp 檔案中呼叫的乙個函式 成員函式 編譯器主要做了下面三件事情 1 名字查詢 先在所在編譯單元中可見名字實體中進行名字查詢 1 類成員函式優先 物件所在的類 基類 一經找到就停止查詢 如果沒有 2 在相應的名字空間中做進一步的...
C 編譯器的函式編譯流程揭秘
c 中的型別查詢過程相對簡單,基本上就是名字查詢,這裡不再介紹。對於 cpp 檔案中呼叫的乙個函式 或成員函式 編譯器主要做了下面三件事情 1 名字查詢 先在所在編譯單元中可見名字實體中進行名字查詢 1 類成員函式優先 物件所在的類 基類 一經找到就停止查詢 2 如果沒有 在相應的名字空間中做進一步...
揭秘 C 編譯器的函式編譯流程
c 中的型別查詢過程相對簡單,基本上就是名字查詢,這裡不再介紹。對於 cpp 檔案中呼叫的乙個函式 或成員函式 編譯器主要做了下面三件事情 1 名字查詢 先在所在編譯單元中可見名字實體中進行名字查詢 1 類成員函式優先 物件所在的類 基類 一經找到就停止查詢 2 如果沒有 在相應的名字空間中做進一步...