我一直在阅读有关virtual
方法的文档:
在虚方法调用中,实例的运行时类型 调用发生的位置决定了实际的方法 要调用的实现。在非虚方法调用中, 编译时类型的实例是决定因素。在 精确术语,当使用参数列表调用名为N的方法时 A在具有编译时类型C和运行时类型R的实例上 (其中R是C或从C 派生的类),调用是 处理如下......: http://msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx
然而,我注意到上面有些大胆的东西。假设我们有这样的代码:
class Planet{
public string Name;
public float Size;
public virtual void SpinPlanet(){
Console.WriteLine("Hoooraaay!!!");
}
}
class Earth : Planet{
}
我的代码中的某处:
Earth world = new Earth();
world.SpinPlanet();
在这种情况下:
SpinPlanet()
Earth
Planet
那么R
如何成为编译时类型C
的派生类。是否在运行时解析基类类型?
答案 0 :(得分:3)
你错了 - 编译时类型(C)是Earth
和运行时类型(R)也是 {{1} }。您指出的规范部分在这里并不重要。
相关的是http://msdn.microsoft.com/en-us/library/aa691356(v=vs.71).aspx,具体是:
构造方法调用的候选方法集。 从找到的与M相关联的方法集开始 通过先前的成员查找(第7.3节),该集合被简化为那些 适用于参数列表A的方法。
Earth
的唯一候选实现恰好位于SpinPlanet
的基类中,而不是在派生类中。
如果代码是:
,则您引用的规范部分将适用Earth
(特别是如果Earth定义了Planet world = new Earth();
world.SpinPlanet();
的覆盖),因为编译类型(变量的类型)将是SpinPlanet
,但运行时类型将是Planet
。< / p>
答案 1 :(得分:2)
调用的正确方法将在运行时通过从Virtual Methods Table中选择来解析。因此,如果您添加到Earth
class Earth : Planet{
public override void SpinPlanet(){
Console.WriteLine("Hoooraaay Earth!!!");
}
}
这样的代码
Planet world = new Earth();
world.SpinPlanet(); //even if declared type Planet,
// the real type remain Earth, so its method will be called
将调用Earth's
方法。
在 my 示例中,编译时类型为Planet
,但运行时类型为Earth
。
在你的示例中,编译时和运行时类型是相同的Earth
。