C#中的虚拟继承

本文关键字:继承 虚拟 | 更新日期: 2023-09-27 18:25:49

当我有一个方法阻止派生类重写基类中定义的虚拟方法时,我与虚拟继承的规则非常混淆。这里有一些代码可以更好地解释我的问题:

using System;
namespace ConsoleApplication1
{
    public class A
    {
        public virtual void DoWork()
        {
            Console.WriteLine("A.DoWork()");
        }
    }
    public class B : A
    {
        public override void DoWork()
        {
            Console.WriteLine("B.DoWork()");
        }
    }
    public class C : B
    {
        public sealed override void DoWork()
        {
            Console.WriteLine("C.DoWork()");
        }
    }
    public class D : C
    {
        public new void DoWork()
        {
            Console.WriteLine("D.DoWork()");
        }
    }
    public class MyMainClass
    {
        public static void Main()
        {
            B b = new D();
            b.DoWork();
            C c = new D();
            c.DoWork();
            A a = new D();
            a.DoWork();
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}

输出

C.DoWork()
C.DoWork()
C.DoWork()
按任意键退出

的确,如果使用类型为B的变量以B b = new C();的形式访问C的实例b.DoWork()将导致调用C的DoWork()实现,因为C覆盖了A.的虚拟DoWork

但是,为什么使用C、B或a类型的变量来访问作为的D实例

B b = new D();
C c = new D();
A a = new D();

在它们中的每一个上调用DoWork()将在类C上调用DoWork[()]的实现?

C#中的虚拟继承

D现在有两个称为DoWork的方法。

第一个方法(方法#1)是在类A中定义并在类C中重写的虚拟方法。D继承了C的这种方法。

第二个方法(方法#2)是在类D中定义的非虚拟方法。这个方法与方法#1完全不同。

现在,您不能从D类型的变量访问方法#1,因为方法#2隐藏了方法#1。

但是,您仍然可以通过使用类型为ABC的变量来访问方法#1。

为了更清楚地说明这一点,这里有一个例子:

D var_d = new D();
B var_b = var_d;
var_d.DoWork(); //This accesses method #2 on an object of type D
var_b.DoWork(); //This accesses method #1 on the same object