CLR implementation of virtual method calls via pointer to base class
直到我知道如何通过C/clr调用所需的虚拟方法时,我才能睡觉。在我的书中,Richter写了不少于clr确定对象的实际类型并调用适当的方法的内容。例如,在C++中,多态类的每个实例都存储指向虚拟表的指针。但在C中,不是指向虚拟表的指针,实例数据存储了一些syncblk索引和typehandle。不理解typehandle与C中的指针的区别。类型句柄的作用是什么?例如,在C++中,我们有
1 2 3 4 5 6 7 8 9 10 11 | class A { int a; public virtual void show() {} }; class B: public A { int b; public virtual void show() {} }; |
A和B类的实例在内存中的外观,我用peseudocode编写
1 2 3 4 5 6 7 8 9 10 11 12 13 | A: { vtptr; // pointer to A vt a; } B: { vtptr; // pointer to A vt + B vt a; b; } |
那么,在C++中,我们运行代码
1 2 |
很明显,我们创建了B实例并将其强制转换为一个类型,但是我们不会丢失show()的重写地址,感谢您调用B::show()。对于C/clr如何执行基类型的强制转换并定义虚方法调用的类似示例,我真的需要理解。请帮助!我很高兴知道所有的技术细节
"Typehandle"是一个流行的错误。它实际上是方法表指针,它在CLR源中命名。一个管理对象的方法与一个C+V-Table功能非常相似,一个指针表与该类方法相似。一个小的差别是,它不只是包含虚拟方法,它还被用来编纂一种方法。
所以,它的工作方式完全一样,一个简单的间接呼唤对着桌子的入口。Jitter知道表中的方法指针的胶印件,就像C+Compiler does。这个运行就像本地的C++Code一样快。
你的Snippet written in C 35;and used like this:
1 2 |
Produces this 32 bit machine code at runtime:
ZZU1
当你可以从胶印(0x38)中说出的时候,方法表中的指针比方法多。您可以在SSCL20源代码中找到详细信息。
The snippet in native C+++and used like this:
1 2 3 4 5 6 |
生产这32位机器代码:
1 2 3 4 5 6 7 8 9 10 11 | 01361010 push 0Ch ; size of B object 01361012 call operator new (136104Ch) ; call operator new 01361017 add esp,4 ; __cdecl stack cleanup 0136101A test eax,eax ; handle null pointer 0136101C je main+1Fh (136102Fh) 0136101E mov dword ptr [eax],offset B::`vftable' (1362100h) ; initialize v-table 01361024 mov edx,dword ptr [eax] ; obtain v-table pointer from object 01361026 mov ecx,eax ; setup this pointer 01361028 mov eax,dword ptr [edx] ; get method pointer 0136102A call eax ; indirect call to show() |
制造商的呼叫是由于语言规则引起的更高的比特。方法呼叫是一样的,只是不同的代码-GEN。在早期一代五丁基处理器上,效率较高。