虚函数 C#

2023-12-07

我明白什么是虚函数。但我不明白的是他们内部是如何工作的?

class Animal
{
    virtual string Eat()
    {
        return @"Eat undefined";
    }
}

class Human : Animal
{
    override string Eat()
    {
         return @"Eat like a Human";
    }
}


class Dog : Animal
{
    new string Eat()
    {
         return @"Eat like a Dog";
    }
}

static void Main()
{
    Animal _animal = new Human();
    Console.WriteLine(_animal.Eat());
    _animal = new Dog();
    Console.WriteLine(_animal.Eat());
}

上述输出给出:

Eat like a Human
Eat undefined

在上面的代码中,_animal 是 Animal 类型,它引用 Human 对象或 Dog 对象。 这是什么意思?我知道内存中 _animal 包含一个指向 Human 或 Dog 对象的地址。它如何决定调用哪个函数。在第一种情况下,我重写,因此调用子级的实现,但在第二种情况下,我使用 new,因此调用父级的实现。你能解释一下幕后发生了什么吗?

提前致谢 缺口


它的工作原理是这样的。想象一下编译器将你的类重写为:

class VTable
{
    public VTable(Func<Animal, string> eat)
    {
        this.AnimalEat = eat;
    }
    public readonly Func<Animal, string> AnimalEat;
}

class Animal
{
    private static AnimalVTable = new VTable(Animal.AnimalEat);
    private static string AnimalEat(Animal _this)
    { 
        return "undefined"; 
    }
    public VTable VTable;
    public static Animal CreateAnimal() 
    { 
        return new Animal() 
            { VTable = AnimalVTable }; 
    }
}

class Human : Animal
{
    private static HumanVTable = new VTable(Human.HumanEat); 
    private static string HumanEat(Animal _this)
    {
        return "human"; 
    }
    public static Human CreateHuman()
    {
        return new Human() 
            { VTable = HumanVTable };
    }
}

class Dog : Animal
{
    public static string DogEat(Dog _this) { return "dog"; }
    public static Dog CreateDog()
    {
        return new Dog() 
            { VTable = AnimalVTable } ;
    }
}

现在考虑这些调用:

Animal animal;
Dog dog;
animal = new Human();
animal.Eat();
animal = new Animal();
animal.Eat();
dog = new Dog();
dog.Eat();
animal = dog;
animal.Eat();

编译器的理由如下:如果接收者的类型是 Animal,那么对 Eat 的调用必须是animal.VTable.AnimalEat。如果接收者的类型是 Dog,那么调用必须是 DogEat。所以编译器将它们写为:

Animal animal;
Dog dog;
animal = Human.CreateHuman(); // sets the VTable field to HumanVTable
animal.VTable.AnimalEat(animal); // calls HumanVTable.AnimalEat
animal = Animal.CreateAnimal(); // sets the VTable field to AnimalVTable
animal.VTable.AnimalEat(animal); // calls AnimalVTable.AnimalEat
dog = Dog.CreateDog(); // sets the VTable field to AnimalVTable
Dog.DogEat(dog); // calls DogEat, obviously
animal = dog;
animal.VTable.AnimalEat(animal); // calls AnimalVTable.AnimalEat

That is exactly怎么运行的。编译器在幕后为您生成 vtable,并且在编译时根据重载决策规则决定是否通过vtable调用.

vtables是在创建对象时由内存分配器设置的。 (我的草图在这方面是一个谎言,因为 vtable 已设置before演员被召唤,而不是之后。)

虚方法的“this”实际上是作为一个不可见的形参秘密地传递给该方法的。

合理?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

虚函数 C# 的相关文章

  • Qt 图表和数据可视化小部件

    我已经安装了 Qt 5 7 来尝试 Qt 图表和 Qt 数据可视化 但我在 Qt Designer 和 Qt Creator 中都找不到新的小部件 有什么建议我应该做什么才能让新的小部件出现在设计器中 我今天遇到了完全相同的问题 默认情况下
  • .NET 单点登录

    我一直在尝试使用 C 为 NET Web 应用程序实现 WEB SSO 服务提供程序插件 我将使用 shibboleth 身份提供商 我已经使用 OpenSAML 库为 java 应用程序实现了相同的功能 我想知道在 NET 应用程序中使用
  • 是否有可能劫持标准输出

    我正在尝试使用 C 重定向 Windows XP 上已运行进程的标准输出 我知道如果我自己生成进程 我可以做到这一点 但对于这个应用程序 我更喜欢一个 监听器 我可以附加到另一个进程 这在纯 Net 中可能吗 如果不可能 在 Win32 中
  • 如何在特定时间以毫秒精度触发 C# 函数?

    我有两台计算机 它们的时间通过 NTP 同步 确保时间仅相差几毫秒 其中一台计算机将通过 TCP 向另一台计算机发送一条消息 以在两台计算机上的未来指定时间启动某个 c 函数 我的问题是 如何在特定时间以毫秒精度 或更好 触发 C 中的函数
  • .crt 部分?这个警告是什么意思?

    我最近收到此警告 VC 2010 warning LNK4210 CRT section exists there may be unhandled static initializers or terminators 我假设这是关键部分
  • 深拷贝和动态转换 unique_ptr

    假设我有一个如下所示的类 class A virtual A class B public A class C public A 我还有一个 unique ptr 向量 它是这样声明的 std vector
  • 在没有 epsilon 的情况下可以将浮点数与 0.0 进行比较吗?

    我知道 要比较两个浮点值 需要使用一些 epsilon 精度 因为它们并不精确 但是 我想知道是否存在边缘情况 我不需要那个 epsilon 特别是 我想知道这样做是否总是安全的 double foo double x if x lt 0
  • Monotouch全局异常处理

    我在野外发现了一只令人讨厌的虫子 但我无法确定它的具体情况 有没有办法拥有全局 Try Catch 块 或者有办法处理 Monotouch 中未处理的任何异常 我可以包起来吗UIApplication Main args 在 try cat
  • Visual Studio 中列表框的上移、下移按钮[重复]

    这个问题在这里已经有答案了 我正在尝试制作一个上移按钮和一个下移按钮 以移动 Microsoft Visual Studio 2012 中列表框中的选定项目 我已经在 WDF jquery winforms 和其他一些表单中看到了其他示例
  • 对作为函数参数传递的指针使用删除

    删除作为函数参数传递的指针是否可以 并且合法 如下所示 include
  • 如何将STL容器数据转储到gdb中?

    我无法在 gdb 中转储 STL 无序映射容器值 变量类型是 std unordered map var 我的 gdb 版本 7 7 1 GDB配置 configure host x86 64 linux gnu target x86 64
  • 如何让XmlReader读取C#中的属性?

    我有一个 XML Stream 其中包含以下 XML 内容
  • 如何从外语线程调用Python函数(C++)

    我正在开发一个程序 使用 DirectShow 来抓取音频数据 媒体文件 DirectShow 使用线程将音频数据传递给回调 我的程序中的函数 然后我让该回调函数调用另一个函数 Python 中的函数 我使用 Boost Python 来包
  • 您对“大规模 C++ 软件设计”的看法 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 正在阅读亚马逊评论 https rads stackoverflow com amzn click com 0201633620 and ACC
  • 如何在 C# 中更改公共 IP 地址

    我正在创建一个 C winform 应用程序 我想在其中更改公共 IP 地址 而不是像 Hotspot Shield ZenMate OpenVPN 等那样更改 IPv4 地址 我已经检查了以下链接 但没有找到足够的帮助 所以我发布了这个问
  • 连接到没有元数据的网络服务

    我想连接到此网络服务 https training api temando com schema 2009 06 server wsdl https training api temando com schema 2009 06 serve
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • 为什么在构造函数中设置字段是(或不是)线程安全的?

    假设您有一个像这样的简单类 class MyClass private readonly int a private int b public MyClass int a int b this a a this b b public int
  • 将一个 IEnumerable 拆分为多个 IEnumerable

    我是 linq 新手 我需要根据指示器将 Couple string text bool Indicator 类型的 IEnumerable 拆分为多个 IEnumerable 我尝试使用skipWhile 和 TakeWhile 但没有找

随机推荐

  • .NET 5 支持旧的 csproj 格式吗?

    从 NET Framework 迁移到 NET 5 时最大的障碍之一是必须将所有 csproj 转换为新的 SDK 样式格式 没有工具可以自动执行此操作 必须手动完成 我想知道这个转换是否有必要 有没有办法在保留旧的 cs 项目的同时切换到
  • 核心 4D 图像 tif 存储为 hdf5 python

    我有 27GB 的 2D tiff 文件 代表 3D 图像电影的切片 我希望能够像简单的 numpy4d 数组一样对这些数据进行切片 看起来 dask array 是一个很好的工具 可以在数组作为 hdf5 文件存储在内存中后干净地操作数组
  • 为什么在字符串数组上使用 Array.map(parseInt) 会产生不同的结果[重复]

    这个问题在这里已经有答案了 我正在观看一个关于销毁所有软件标题的演讲JavaScript 的诞生与消亡 在演讲中 Gary Bernhardt 指出了 JavaScript 的一个奇怪的功能 即给出一个整数字符串数组 javascript
  • 在R中是否可以得到F#的函数应用“|>”运算符? [复制]

    这个问题在这里已经有答案了 可能的重复 R 流水线函数 我发现 R 语法与 F 相比非常笨拙 在 R 中 而不是 plot exp cumsum returns 我很想做 returns gt cumsum gt exp gt plot 有
  • Bootstrap 4 - 以自定义方式显示卡片

    我正在尝试创建一个基于 Bootstrap 4 的正确语义 HTML CSS 它将以某种方式呈现卡片元素 而无需添加太多自定义批量 到目前为止我所拥有的是这样的 section class section d flex align item
  • 可扩展的 WinForms 文本框

    我在 Windows 窗体应用程序中创建了一个文本框 该文本框以用于在单行中输入文本的高度开始 但我希望如果用户输入包含在控件内的文本 文本框会自动增加其高度 目前 对于此文本框 我将属性 multiline 和 wordwrap 设置为
  • 为什么编译器需要一个特征的实现来调用默认的自由函数?

    当调用一个不需要的特征的默认实现时self 为什么需要注释一个实现类型呢 A 最小的 可重现的例子在下面 操场 mod builder pub trait Builder Sized fn new gt Simple Simple pub
  • 谷歌 protobuf 和 A​​ndroid NDK

    如何构建Google protobuf c 版本 https github com google protobuf releases latest 与 Android 目标 我在没有 ndk build 的情况下编译了 protobuf 这
  • 在jsp中显示数据

    我是jsp新手 面临一个问题 我需要创建 jsp 页面 显示来自 servlet 的数据 Servlet 代码 protected void doGet HttpServletRequest request HttpServletRespo
  • 尝试到达应用程序引擎端点时出现 SSLHandshakeException

    我正在尝试从 Android 客户端连接到我的端点方法之一到本地运行的应用程序引擎后端 问题是我收到 SSLHandshakeException 我的 API 不受 OAuth 保护 我试图达到的方法如下所示 ApiMethod name
  • 从被调用方法捕获异常

    关于程序流程 这个问题已经困扰我一段时间了 我想知道是否可以从方法中捕获错误 以阻止它执行通常遵循它的方法 如下例所示 我无法开始工作 public class MyClass public static void main String
  • 忽略 py2exe 中的library.zip

    我需要一个可执行文件 exe 它从文件中获取一些参数 用户可以根据他 她的需要配置这些参数 由于我在 python 中创建了脚本 因此我使用 py2exe 来创建该可执行文件 虽然我可以放置一个名为的可配置文件设置 dat作为数据文件并用它
  • 如何将 jackson objectmapper dateformat 配置添加到 spring mvc 配置中?

    我有一个关于 Jackson 2 1 的问题 我的 pojo 有一些日期属性 我想将其转换为字符串 我将其解决在 spring servlet xml 中 但它没有用 我不喜欢使用 JsonSerialize using JsonDateS
  • Android:从特定电话号码接收短信

    我的应用程序是否可以从特定电话号码接收短信 而不让它触发系统通知 但让所有其他消息传递到默认短信应用程序进行正常处理 如果是这样 系统如何知道哪个进程首先进入队列来选择接收哪些消息 我没有尝试这个 但理论上它应该有效 在 Android 中
  • 如何从 Java 中的 JSON 字符串中删除元素?

    我有一个 json 作为字符串 我需要使用 java 代码从中删除一个元素 感谢你的帮助 Example 尝试了数组和其他东西 但没有运气 输入 需要删除图像 widget debug on window title Sample Konf
  • 复制 java.util.Random 类型的实例变量以创建相同状态的对象

    我正在实施一个模拟退火 SA 算法 我需要复制状态 例如记住迄今为止的最佳解决方案 我实现了一个复制方法 因为不鼓励使用java的clone SA 是一种启发式算法 因此下一步要采取的步骤是随机确定的 这是通过使用Random对象 我也想复
  • 如何在 Windows 10 上使用 IPC::Run 捕获超时异常?

    我正在尝试捕获超时异常IPC Run在 Windows 10 上 使用 Strawberry Perl 版本 5 30 1 use strict use warnings use feature qw say use Data Dumper
  • 最小化工作簿/工作表但保持表单打开

    有没有办法最小化工作簿 工作表但能够保持表单打开 我已经尝试过代码 application visible false and userform1 show vbmodeless 但这会隐藏所有活动的工作簿 并且工具栏功能区也会消失 有没有
  • 获取属于个人 Triadic Census 类别的 Triad 节点列表

    通过执行 Networkx triadic census 算法 我可以获得每种类型的三元普查中节点数量的字典 triad census social nx triadic census social graph to directed 现在
  • 虚函数 C#

    我明白什么是虚函数 但我不明白的是他们内部是如何工作的 class Animal virtual string Eat return Eat undefined class Human Animal override string Eat