当父变量类型存储子对象并调用重写的方法时会发生什么

本文关键字:方法 什么 重写 调用 类型 变量 存储 对象 | 更新日期: 2023-09-27 18:24:09

当父变量类型存储子对象并调用被子类重写的方法时会发生什么?

方法的父版本执行还是子版本执行?

public class testa
{
    public virtual void display()
    {
        System.Diagnostics.Debug.WriteLine('a');
    }
}
public class testb : testa
{
    public override void display()
    {
        System.Diagnostics.Debug.WriteLine('b');
    }
}

然后打电话给

testa b = new testb();
b.display();

通过自己运行这个测试,我发现它写着"b",尽管我仍然希望得到一个正式的答案,以完全了解正在发生的事情。

当父变量类型存储子对象并调用重写的方法时会发生什么

您指的是运行时多态性。当一个对象上有一个virtual method is called时,那么方法的most derived version总是gets called

与您的情况类似,您正在调用display(虚拟)方法,该方法在testb类中被覆盖。因此,它被调用来显示b

testa b = new testb();
b.display();

但是,如果您使用method hiding,则使用new关键字-

public class testa
{
    public void display()
    {
        System.Diagnostics.Debug.WriteLine('a');
    }
}
public class testb : testa
{
    public new void display()
    {
        System.Diagnostics.Debug.WriteLine('b');
    }
}

你运行这个代码-

testa b = new testb();
b.display();

您将看到a被打印,因为base class method gets called是它的no more virtual

如果还不清楚,请参阅覆盖VS方法隐藏链接以获得更详细的解释。

当您创建一个包含虚拟函数的类时,您会得到一个称为虚拟表(或vtable)的东西vtable通过类中的地址保存指向该类中所有虚拟函数的指针。

当您持有指向父类(实际上是派生类)的指针并调用虚拟函数时,将访问vtable以获取函数的地址,并以实际派生类型运行函数。

这是一个大主题,你最好读一读。还有一些我没有提到的东西,比如对象大小是如何随着指针的大小而增加的,或者vtable实际保存的在哪里

http://en.wikipedia.org/wiki/Virtual_method_table