C# virtual关键字调用方法的大多数派生定义吗?

C# virtual关键字调用方法的大多数派生定义吗?,c#,.net,oop,polymorphism,C#,.net,Oop,Polymorphism,我正在读这篇文章 我读到:“.当对一个对象调用虚方法时,就会调用该方法的最派生版本” 但当我执行以下代码时: class A { public virtual void print() { Console.WriteLine("A called"); Console.Read(); } } class B :A { public override void print() { Console.WriteL

我正在读这篇文章

我读到:“.当对一个对象调用虚方法时,就会调用该方法的最派生版本”

但当我执行以下代码时:

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 override void print()
    {
        Console.WriteLine("C called");
        Console.Read();
    }
}

static void Main(string[] args)
{
    B b = new B();
    b.print(); it prints B?

}
它打印B。如果上述说法属实,不应该是“C”吗?
我错过了什么?在此上下文中,“最派生的”是什么意思?

它将从调用它的实例的类型调用方法,您使用类
B
的实例调用它,因此将调用
B
的实现,若您使用的是类
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();
    }
}
现在如果你这样称呼它:

static void Main(string[] args)
{
    A a = new C();
    a.print(); // it prints C (most derived implementation called) 
    B b = new C();
    b.printfromB(); // it prints "printfromB in C called"

}

当实际类型为
B
时,不可能调用
C

最初的“最衍生”术语可通过以下方式理解:

A data = new C();
data.print();
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.print
B.print
,而是
C.print
)(这是因为该方法是
虚拟的


我想你对答案中的术语感到困惑了

这里有两件事

  • 被实例化的派生类上下文中方法的大多数派生版本
  • 所以如果你这样做

    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 data = new C();
    data.print();
    
    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是否引用了B或C。客户端代码中的行为会动态变化

  • 或者,您也可以通过以下方式考虑大多数派生版本:
  • 假设方法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())
    }
    
    希望这个答案有帮助


    最佳。

    调用实际实例的最派生部分-如果实例化B,则会打印B。尝试
    A=newb();a、 打印()
    A=新的C();a、 打印()
    @Marwie它会打印a,它会打印B或C。试试看。作为一个思维实验,想象另一个类
    D:B
    。。。在你的例子中,如果它应该输出“C called”,那么它会用额外的类写“C called”或“D called”(显然答案是两者都不是)。但是为什么要使用“最派生”的版本呢?作者可能只会说“派生”的版本。还有什么吗?作者可能是想说,如果您创建了most派生的实例,那么将调用most派生的重写实现。@Arbaaz您已经重写了同一个方法两次。因此,如果像Ehsan Sajjad的示例中那样执行
    a.print()
    ,将执行该方法最派生的版本。对于C的实例,C的
    print
    方法将获胜-即使C是从B派生的,B本身已经实现了
    print