我在C#中有一个代码示例
using System;
class A
{
public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
static void Main() {
D d = new D();
A a = d;
B b = d;
C c = d;
a.F();
b.F();
c.F();
d.F();
}
}
此代码大纲
B.F
B.F
D.F
D.F
我不明白为什么a.F(); 有B.F?
MS如何表示虚拟方法是由对象类型实时表示的
答案 0 :(得分:1)
我不明白为什么a.F();有B.F?
调用虚方法时,对象的运行时类型为 检查一个压倒一切的成员。最重要的成员 派生类称为,如果不是,则可能是原始成员 派生类已重写成员。
大胆的内容会向您解释调用B.F
时打印A.F()
的原因。
答案 1 :(得分:1)
从继承的类对象调用方法F()会打印出类型为D的对象的B.F,因为你覆盖了类B(和类D)中的方法。
您的测试几乎完全是this MSDN post on virtual methods中提供的示例的副本:
using System;
class A
{
public void F() { Console.WriteLine("A.F"); }
public virtual void G() { Console.WriteLine("A.G"); }
}
class B: A
{
new public void F() { Console.WriteLine("B.F"); }
public override void G() { Console.WriteLine("B.G"); }
}
class Test
{
static void Main() {
B b = new B();
A a = b;
a.F();
b.F();
a.G();
b.G();
}
}
在该示例中,A引入了非虚方法F和虚拟方法 方法G.因此,B类引入了一种新的非虚方法F. 隐藏继承的F,并且还会覆盖继承的方法G. 示例生成输出:
A.F
B.F
B.G
B.G请注意该声明 a.G()调用B.G,而不是A.G.这是因为运行时类型的 instance(即B),而不是实例的编译时类型 (即A),确定要调用的实际方法实现。 因为允许方法隐藏继承的方法,所以它是可能的 一个类包含几个具有相同的虚方法 签名。这不会产生歧义问题,因为除了 最派生的方法是隐藏的。在示例中
答案 2 :(得分:1)
如果是a.F(),则存在B.F,因为A类中的虚拟空虚F在B中被覆盖。
它不会被C覆盖,因为有一个新的运算符不会覆盖虚拟基本方法。
因此,如果有一个D类型的实例输入到A并且您调用F(),则会调用A类中的虚方法,但会考虑最新的覆盖。那是B.F。