C#中虚拟方法的外线

时间:2016-06-21 06:43:06

标签: 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如何表示虚拟方法是由对象类型实时表示的

3 个答案:

答案 0 :(得分:1)

  

我不明白为什么a.F();有B.F?

MSDN #

  

调用虚方法时,对象的运行时类型为   检查一个压倒一切的成员。最重要的成员   派生类称为,如果不是,则可能是原始成员   派生类已重写成员。

大胆的内容会向您解释调用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。