virtual关键字是否调用方法的大多数派生定义?

时间:2016-01-07 12:31:14

标签: c# .net oop polymorphism

我正在读这篇文章 Overriding vs method hiding

我读到了“ ..当在对象上调用虚方法时,该方法的派生版本最多被称为

但是当我执行以下代码时:

struct C : A, B {
     C& operator=(C&& c) {
         static_cast<A&>(*this) = static_cast<A&&>(c);
         return *this;
     }
};

打印B。如果以上引用的陈述是真的,它不应该是“C”吗? 我错过了什么?在这种情况下,“大多数派生”是什么意思?

3 个答案:

答案 0 :(得分:1)

它将从调用它的实例的类型调用方法,您使用类B的实例调用它,因此如果您使用类的实例,将调用B的实现<{1}}然后会调用C类的重写实现。

例如:

C

现在如果你这样称呼它:

class B :A
{
    public override void print()
    {
        Console.WriteLine("B called");
        Console.Read();
    }
    public virtual void printfromB()
    {
        Console.WriteLine("printfromB in B called");
        Console.Read();
    }
}
class C : B
{
    public override void print()
    {
        Console.WriteLine("C called");
        Console.Read();
    }
    public override void printfromB()
    {
        Console.WriteLine("printfromB in C called");
        Console.Read();
    }
}

答案 1 :(得分:0)

当实际类型为C时,无法调用B

原始的“大多数派生”术语可以使用以下内容来理解:

A data = new C();
data.print();

即使编译器将data视为A派生的(不是A.printB.print,但是C.print)将调用版本(这是因为该方法是virtual)。

请参阅Polymorphism

答案 2 :(得分:0)

我认为你对答案中单词的技术性感到困惑。

这里有两件事,

  1. 在实例化派生类的上下文中,该方法的大多数派生版本。
  2. 如果你这样做,

    A a = new B();
    a. print(); // this will invoke the method on the class B,
                    // since instance of class A has reference to instance of B.
    

    如果您执行以下操作:

    A a = new C();
    a. print(); // Should call the method on class C, since base class has reference to to the instance of C.
    

    同样,更直观的方式是:

    A a = new A();
    a.print(); // this will call the method print in class A irrespective of whether this method was overriden in one of the derived classes.
    

    这是动态多态的前提,其中,客户端可以在A的基类对象上调用方法print() 无需知道A是否引用了B或C.行为在客户端代码中动态变化。

    1. 或者,您也可以通过以下方式考虑大多数派生版本:
    2. 假设方法print()未在C中覆盖,但在B中被覆盖, 那么print()的派生版本将在B类中。以下片段应该会有所帮助。

      class A
      {
          public virtual void print()
          {
              Console.WriteLine("A called");
              Console.Read();
          }
      }
      class B :A
      {
          public override void print()
          {
              Console.WriteLine("B called");
              Console.Read();
          }
      }
      class C : B
      {
          public void somerandommethod()
          {
              // some random method not really relevant to this example.
          }
      }
      
      static void Main(string[] args)
      {
          A a = new C();
          a.print(); // it will now print B (since B has the most derived implementation of print())
      }
      

      希望这个答案有所帮助。

      最佳。