Cla*_*Tan 21 .net c# inheritance
继承链如下:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
class Program
{
static void Main(string[] args)
{
A tan = new D();
tan.Foo();
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
结果是,调用了B类中的方法foo().
但在参考中:
调用虚方法时,将检查对象的运行时类型是否有覆盖成员.如果没有派生类重写成员,则调用派生程度最大的类中的重写成员,该成员可能是原始成员.
在我的逻辑中,CLR首先发现Foo()
是一个虚方法,它查看D
运行时类型的方法表,然后它发现在这个最派生的类中有一个重写成员,它应该调用它并且永远不会意识到有一个new Foo()
在继承链.
我的逻辑出了什么问题?
Eri*_*ert 34
艾米的回答是正确的.这是我喜欢看这个问题的方式.
虚方法是可以包含方法的插槽.
当要求进行重载解析时,编译器确定在编译时使用哪个插槽.但运行时确定该槽中实际的方法.
现在考虑到这一点,让我们看看你的例子.
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
进入第二个插槽.那么现在你的电话会怎么样?
编译器的原因是你正在调用Foo
编译时类型A
,所以它找到第一个(也是唯一的)Foo
插槽A
.
在运行时,该插槽的内容是B.Foo
.
这就是所谓的.
现在有道理吗?
Amy*_*Amy 29
调用虚方法时,将检查对象的运行时类型是否有覆盖成员.如果没有派生类重写成员,则调用派生程度最大的类中的重写成员,该成员可能是原始成员.
你是从错误的地方开始的.您的变量是类型A
并包含实例D
,因此使用的虚拟表是A
's 1.在上面的文字之后,我们检查一个压倒一切的成员.我们找到一个B
. C
不计算因为它没有覆盖,它是阴影基本方法.而且,由于D
覆盖C
,不是A
或者B
,它也不算重要.我们正在寻找最派生类中的重写成员.
所以发现的方法是B.Foo()
.
如果你改变C
它覆盖而不是阴影,那么找到的方法将是D
,因为它是派生最多的重写成员.
如果您改为将对象更改为B
或的实例C
,B.Foo()
则仍将是所选的覆盖.澄清一下,这就是我的意思:
A tan = new B();
tan.Foo(); // which foo is called? Why, the best Foo of course! B!
Run Code Online (Sandbox Code Playgroud)
B
调用的原因是因为我们正在搜索的继承链从A
(变量类型)跨越到B
(运行时类型). C
并且D
不再是该链的一部分,并且不属于虚拟表.
如果我们改为将代码更改为:
C tan = new D();
tan.Foo(); // which foo, which foo?
Run Code Online (Sandbox Code Playgroud)
我们搜索的继承链从跨越C
到D
. D
是有一个压倒一切的成员,所以它Foo
被称为.
假设您添加了另一个Q
继承自A
,R
继承自Q
,等等的类.你有两个继承分支,对吧?在搜索大多数派生类型时选择哪个?遵循从A
(您的变量类型)到D
(运行时类型)的路径.
我希望这是有道理的.
1不是字面意思.虚拟表属于,D
因为它是运行时类型并包含其继承链中的所有内容,但它有用且更容易被A
视为起点.毕竟,您正在搜索派生类型.
归档时间: |
|
查看次数: |
1315 次 |
最近记录: |