当对象隐藏基类成员时,当对象引用存储在基类变量中时,我试图理解CLR如何正确调度方法调用。
让我感到困惑的是由运行时创建的对象头。堆上的对象头有两个字段:类型指针和同步块索引。类型指针指向类的方法表。即使对象引用是基类,在堆上创建的对象也是派生类。这将导致运行时使用派生类对象的方法表。但是运行库正确地调用基类成员。
你能帮我理解一下流程吗?在这种情况下,CLR是如何正确调用这些方法的?
发布于 2012-08-18 18:06:35
记录在object头中的对象类型在这里并不重要。编译器发出方法调用,命名应该调用其方法的特定类。在生成的IL中非常明显。例如:
class Base {
void foo() { }
void callFoo() {
foo(); // <== here
}
}
class Derived : Base {
new void foo() { }
}指定的语句生成此IL:
IL_0002: call instance void ConsoleApplication1.Base::foo()注意call操作码中存在Base,没有歧义。
发布于 2012-08-18 18:09:36
调用不是虚拟的或以任何方式被重写的方法与方法表没有任何关系。C#编译器按名称调用该方法(程序集实际上包含字符串形式的名称!)并且JIT将函数的地址硬编码为发出的x86代码。该地址不依赖于this对象引用的运行时类型。
https://stackoverflow.com/questions/12017538
复制相似问题