2016-06-21 49 views
0

我的代码的一个例子在C#输出线在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如何表示,虚拟方法是通过在实时类型的对象represended

回答

1

我不理解为什么在壳体a.F();有B.F?

MSDN #

当调用虚拟方法,所述对象的运行时类型是 检查用于重写构件。 派生类中的首要成员称为,如果没有 派生类已重写成员,则该成员可能是原始成员。

粗体内容将向您解释为什么在调用A.F()时打印B.F

1

从继承的类对象对方法F()的调用将类型D对象的B.F转换为类型A,因为您重写了类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的 例产生输出:

AF
BF
BG
BG

注意,声明 AG()调用BG,而不是AG这是因为运行时类型的 实例(即B),而不是在编译时类型实例 (即A)确定要调用的实际方法实现。 由于允许方法隐藏继承的方法,因此类 可能包含几个具有相同 签名的虚拟方法。这并不存在歧义问题,因为除了最衍生的方法以外,其他所有方法都是隐藏的。在该示例中

1

在AF()的情况下,存在因为BF虚拟无效的F类A是覆盖在B.

它不是被C覆盖,因为有一个新的运营商,其不重写虚拟基础方法。

因此,如果有类型为D的类型D的实例并且您调用F(),则会调用类A的虚拟方法,但会考虑最新的覆盖。那就是B.F.