.net C#中虚函数的函数调用顺序是什么?

q3aa0525  于 2023-03-09  发布在  .NET
关注(0)|答案(4)|浏览(149)

我有这个代码:

namespace ConsoleApplicationDemo
{
    class base 
    {
        public virtual void   Sum()
        {
            Console.WriteLine("Sum in base ");
        }
    }
    class Program:base 
    {

        public override void Sum()
        {

            Console.WriteLine("SUM  IN Program ");
        }

        static void Main(string[] args)
        {

            base A2 = new Program();
            A2.Sum();
            Program P2 = new Program();
            P2.Sum();
            Console.ReadLine();
        }
    }
}

获取输出:SUM IN程序SUM IN程序
我的问题是为什么基类Sum函数没有被这段代码调用?

base A2 = new Program();
A2.Sum();
mv1qrgav

mv1qrgav1#

这是因为您重写了基类实现。Virtual/Override表示“嘿,每次调用此方法时都使用重写的方法。”
如果你已经用new关键字标记了子类函数,那么它将执行你所描述的操作(就我个人而言,我不喜欢使用new关键字,因为大多数人不理解它实现的细微差别,但是它执行你所描述的行为。还有更好的替代方法)。
Article describing new keyword.

fgw7neuy

fgw7neuy2#

标记为重写的方法将重写其基方法的完整实现。因此,如果创建派生类Program的示例,则会调用此重写方法。但是,您也可以使用base.Sum()从派生方法中调用基实现

public override void Sum()
{
    base.Sum();  // now you see why base is a really bad name for your class
    Console.WriteLine("SUM  IN Program ");
}
tzxcd3kk

tzxcd3kk3#

多态性改变了子类的实现,即使你将子类引用向上转换到基类,你也不能访问基类virtual的方法实现,而是对象继承的最深层实现。
另一方面,派生类可以使用base关键字有效地访问基类实现:

public override void Sum()
{
     // This calls base implementation.
     base.Sum();

     Console.WriteLine("SUM  IN Program ");
}

无论如何,base将调用直接基类的实现。您将不能调用继承树中高于一级的实现。

dbf7pr2w

dbf7pr2w4#

new关键字描述了创建了什么实际类型,变量类型base意味着它至少可以作为base类型被引用(使用)。
考虑基类B和派生类A

public class B { }
public class A: B { }

然后new B()在内存中创建基类,new A()在内存中创建派生类。
你可以将这些对象的引用存储在它们各自的类或任何基类中,你甚至可以使用object来保存引用,因为它是C#中所有东西的基类。

B x1 = new B();
A x2 = new A();
B x3 = new A();
A x4 = new B(); // error: not allowed
object x5 = new B();
object x6 = new A();

具体地说,无论内存中使用new关键字初始化的类型是什么,都将调用.Sum()函数,而不考虑持有变量的类型。
PS.使用base作为名称是个坏主意,因为它是C#关键字。

相关问题