namespace demo在essential .net中,don box向讀者簡單描述了基於介面的多型呼叫,在堆中有乙個全域性介面對映表,當某個類實現了乙個介面,就會在這個介面表中增加項,而增加的這些項又指向這個具體類的method table中的method,可能說的不是太清楚,就用個圖來表示:public
class
base : ifoo
}class
program}}
當進行方法呼叫的時候,首先通過物件找到該型別的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.在子類中重寫虛方法需要注意哪些問題?首先說明的是,子類中的重寫並不是必須的,...