程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++中的名字查找問題解答

C++中的名字查找問題解答

編輯:關於C++

朋友最近發郵件問我兩個問題。內容如下(為了更適合閱讀,我做了簡單修改。譯者在此基礎上又做了修改):

我在C++的多繼承上遇到了很大麻煩。

如圖1,A、B1和B2為純抽象類;C從B1、B2多繼承,且實現了全部父類的抽象方法。

圖1

現在:

C* p = new C;
p->Method_of_A(); //從B1、B2都能得到被調用方法,為什麼編譯器不報“二義性”(ambiguity)錯誤呢?

而按圖2結構實現繼承關系後:

圖2

B4* p = new C;
p->Method_of_A();

編譯器(VC++)認為有二義性。經調試我發現編譯過程中使用了“adjustor thunk”(譯者注:具體請參看http://blog.sina.com.cn/u/491874bb010004xq或Stan Lippman的《Inside the C++ Object Model》)。希望您能解答這兩個問題,以幫助我更好理解C++(更確切的說是VC++)中的MI(多繼承)機制。

好,我們深入研究下這個問題。

上述編譯器行為的差異,與繼承關系的復雜度、vtable以及adjustor thunk並無直接關系,它其實就是一個名字查找(name lookup)過程(以本例而言,就是查找方法“Method_of_A”)。

在C++中,函數編譯時檢查過程如下:

第一步,執行名字查找(name lookup):在調用類中查找,並生成候選列表;若候選列表為空,再擴大查找范圍(如名字空間內,或父類);如此循環。如果最終無結果,那麼抱歉,就會提示你“名字未能找到”;否則,編譯器跳到第二步。

第二步,執行重載辨別(overload resolution):如果第一步得到的候選者個數大於一,編譯器將以傳遞給函數的參數及其類型為依據,嘗試找到最佳答案。如果無法據此確定最優者,就會報告“存在二義性調用”。

第三步,可見性檢查(accessibility checking):編譯器檢查是否可真正執行調用(比如,被調用函數是否是私有的)。

總而言之一句話,上述三個過程,都實現於對象的靜態類型基礎上,與實例無關。

問題1:

C* p = new C;
p->Method_of_A();

名字查找就只會在C中進行,根本不會達到A,實際就是直接調用C::Method_of_A.

而在問題2中:

B4* p = new C;
p->Method_of_A();

使用的對象類型是B4,而B4本身沒有提供Method_of_A,因此會到其父類B1、B2中查找,結果找到兩個,且不能通過重載辨別實現優化,因此報告存在二義性。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved