Will CLR check the whole inheritance chain to determine which virtual method to call?
继承链如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class A { public virtual void Foo() { Console.WriteLine("A's method"); } } class B:A { public override void Foo() { Console.WriteLine("B's method"); } } class C:B { public new virtual void Foo() { Console.WriteLine("C's method"); } } class D:C { public override void Foo() { Console.WriteLine("D's method"); } } |
然后:
1 2 3 4 5 6 7 8 9 |
结果是,调用了类B中的foo()方法。
但在参考文献中:
When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member.
在我的逻辑中,clr首先发现
我的逻辑怎么了?
艾米的回答是正确的。下面是我如何看待这个问题。
虚拟方法是可以包含方法的槽。
当被要求执行重载解析时,编译器决定在编译时使用哪个槽。但是运行时决定了该槽中实际是什么方法。
现在考虑到这一点,让我们看看您的例子。
A 有一个用于Foo 的插槽。B 有一个槽位给Foo 继承来自A 。C 有两个用于Foo 的插槽。一个继承自B ,和一个新的。你说你想要一个叫foo的新槽,所以你得到了。D 有两个槽供Foo 使用,继承自C 。
这就是吃角子老虎机。那么,这些槽里有什么?
- 在
A 中,A.Foo 进入插槽。 - 在
B 中,B.Foo 进入插槽。 - 在
C 中,B.Foo 进入第一槽,C.Foo 进入第二槽。记住,这些插槽完全不同。你说你想要两个同名的吃角子老虎机,所以这就是你想要的。如果这让人困惑,那就是你的问题。如果你这样做很痛,就不要这样做。 - 在
D 中,B.Foo 进入第一槽,D.Foo 进入第二槽。
那么现在你的电话怎么了?
编译器的原因是您在编译时类型
在运行时,该插槽的内容是
所以这就是所谓的。
现在明白了吗?
When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member.
你从错误的地方出发。您的变量是
所以找到的方法是
如果更改
如果将对象改为
1 2 |
之所以调用
如果我们改为将代码改为:
1 2 |
我们搜索的继承链从
假设您添加了另一个继承
我希望这是有道理的。
1不是字面意思。虚拟表属于