CLR怎樣實現虛方法的多型呼叫(2)

2021-09-05 17:32:02 字數 1562 閱讀 2885

namespace demo

public

class

base : ifoo

}class

program}}

在essential .net中,don box向讀者簡單描述了基於介面的多型呼叫,在堆中有乙個全域性介面對映表,當某個類實現了乙個介面,就會在這個介面表中增加項,而增加的這些項又指向這個具體類的method table中的method,可能說的不是太清楚,就用個圖來表示:

當進行方法呼叫的時候,首先通過物件找到該型別的method table,根據偏移量找到指向inte***ce offset table的指標來定位這個inte***ce offset table,然後clr查詢呼叫方法在這個offset table的偏移量,最後呼叫該方法。呼叫的彙編**如下:

mov ecx, esi  -- 儲存物件位址到ecx中

mov eax, dword ptr [ecx] -- 把型別的method table的位址儲存在eax中

mov eax, dword ptr [eax+0ch] -- 把inte***ce offset table的位址儲存在eax中

mov eax, dword ptr [eax + inte***ce offset] -- 根據inte***ce在table中的偏移量,找到其位址並儲存到eax中

call dword ptr [eax +  method offset] -- 根據該方法的偏移量定位改方法進行呼叫

可以說這樣的呼叫邏輯是很清楚容易讓人理解的。

但是當我用windbg進行跟蹤的時候卻發現介面方法呼叫機制和上面所說的不同,並沒有乙個查詢inte***ce offset table的過程,在main函式裡是這樣的呼叫:

mov ecx, esi --  儲存物件位址到ecx中

call dword ptr ds:[980010h]  在資料段980010h上儲存的是乙個指標,實際上呼叫的是:

jmp mscorwks!resolveworkerasmstub

可以看到跳轉到resolveworkerasmstub函式裡去了。而這個函式是做什麼的呢,下面的**是從sscli裡面找到的(有興趣的可以看看virtualcallstubcpu.hpp):

__declspec (naked) void resolveworkerasmstub()
// 首先儲存暫存器狀態

call virtualcallstubmanager::resolveworkerstatic //呼叫resolveworkerstatic方法
//還原暫存器狀態
jmp eax //eax儲存著實際上要呼叫的方法的位址,所以這裡就開始了方法呼叫
所以猜想到在virtualcallstubmanager::resolveworkerstatic函式裡面正確找到了方法的位址,儲存在eax裡。

看來到底是怎樣取到該方法位址這個問題只能等下次有時間再用windbg跟蹤。如果有人了解,也希望能解釋一下來幫助我解答疑惑。

多型和虛方法的呼叫

1.多型 多型 是指在乙個程式中相同的名字表示不同的含義。編譯時的多型 過載 多個同名的不同的方法.例如我們給定的引數個數不同執行不同的功能。執行時的多型 覆蓋 子類對父類方法的覆蓋。動態繫結 虛方法呼叫。在呼叫方法時,程式會正確呼叫子類方法的物件。多型的特點大大提高了程式的抽象程度和簡潔性。2.上...

虛方法實現多型

大家都知道物件導向的三大特徵,封裝 繼承 多型,這裡解釋一下多型 同一操作作用於不同的物件,可以有不同的解釋,產生不同的執行結果,這就是多型性。換句話說,實際上就是同乙個型別的例項呼叫 相同 的方法,產生的結果是不同的。這裡的 相同 打上雙引號是因為這裡的相同的方法僅僅是看上去相同的方法,實際上它們...

多型實現之 虛方法

多型實現共有三種途徑,分別是 虛方法 抽象類 介面,本篇講述第一種方法 虛方法。1.什麼是虛方法?虛方法,從語法上來說是被virtual關鍵字修飾的方法,從含義上講,這個方法在類被繼承後可以在子類重寫 override 2.在子類中重寫虛方法需要注意哪些問題?首先說明的是,子類中的重寫並不是必須的,...