C# 继承、多态、虚方法表(VTable)原理

一、先理清:继承 → 多态 → VTable 的关系

  • 继承:子类复用父类的成员,还能重写 / 扩展
  • 多态 :父类引用指向子类对象,调用方法时自动执行子类的实现(运行时决定)
  • 虚方法表(VTable) :C# 实现多态的底层数据结构,CLR 靠它找到正确要执行的方法

一句话总结:继承让多态成为可能,虚方法表让多态能够真正运行。

二、基础概念快速回顾

1. 继承 (Inheritance)
  • 一个类(子类 / 派生类)可以复用另一个类(父类 / 基类)的字段、属性、方法

  • 关键字::

  • 单继承:一个类只能有一个直接父类

    cs 复制代码
    // 父类
    public class Animal
    {
        public void Eat() => Console.WriteLine("吃食物");
    }
    
    // 子类:继承 Animal
    public class Dog : Animal
    {
        public void Bark() => Console.WriteLine("汪汪叫");
    }

    Dog 自动拥有 Eat(),还能新增自己的 Bark()

2. 多态 (Polymorphism)

定义 :同一个父类引用,指向不同子类对象,调用同名方法会执行对应子类自己的逻辑。

实现多态必须用三个关键字:

  • virtual:父类方法标记为虚方法(可被重写)
  • override:子类重写虚方法
  • abstract / interface:也能实现多态(原理一致)

多态代码示例

cs 复制代码
// 父类:标记虚方法
public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("动物叫");
    }
}

// 子类1:重写
public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("汪汪汪");
    }
}

// 子类2:重写
public class Cat : Animal
{
    public override void Speak()
    {
        Console.WriteLine("喵喵喵");
    }
}

多态核心用法:

cs 复制代码
// 父类引用 指向 子类对象
Animal animal1 = new Dog();
Animal animal2 = new Cat();

// 运行时自动执行对应子类的方法!
animal1.Speak(); // 汪汪汪
animal2.Speak(); // 喵喵喵

三、虚方法表 VTable 原理

1. 什么是 VTable?

VTable(Virtual Method Table,虚方法表) 是.NET CLR 在内存中为每个包含虚方法的类 创建的一个方法地址数组。

作用:运行时快速找到应该执行哪个重写方法 → 实现多态。

2. VTable 生成规则
  • 每个有虚方法的类 ,都会生成一张独立的 VTable
  • 子类 VTable 完全复制父类 VTable
  • 如果子类重写(override)了虚方法,就替换表中对应的方法地址
  • 每个对象实例内部,都藏着一个指针(TypeHandle) 指向自己类的 VTable
3. 内存结构图解(文字版)

以上面的 Animal/Dog/Cat 为例:

① 父类 Animal VTable

cs 复制代码
[0]:Animal.Speak()

② 子类 Dog VTable(复制后替换)

cs 复制代码
[0]:Dog.Speak()  // 重写了,替换父类方法

③ 子类 Cat VTable

cs 复制代码
[0]:Cat.Speak()  // 重写了,替换父类方法
4. 多态执行流程(CLR 底层步骤)

当你执行:

cs 复制代码
Animal animal = new Dog();
animal.Speak();

CLR 做了 4 步:

  1. 看 animal 引用指向的真实对象 :Dog
  2. 找到对象里的 TypeHandle 指针
  3. 定位到 Dog 的 VTable
  4. 根据方法索引找到 Dog.Speak() 并执行

这就是多态的底层真相:不是看引用类型,是看对象真实类型!

四、关键关键字对比

关键字 作用 是否进 VTable
virtual 父类声明:可被重写 ✅ 进入 VTable
override 子类重写:替换 VTable 方法地址 ✅ 替换 VTable 项
new 子类隐藏父类方法:不是重写 ❌ 不进 VTable,不实现多态

特别注意:new 关键字不会生成多态!

五、VTable 核心特性总结

  • 类级别,不是对象级别一个类只有一张 VTable,所有对象共享这张表

  • 继承时复制 + 重写时替换子类完全继承父类虚方法表,重写就替换对应位置

  • **运行时绑定(晚绑定)**方法地址不是编译时写死,而是运行时查表决定

  • 只有虚方法 / 重写方法才进 VTable 普通实例方法、静态方法不进虚方法表

    cs 复制代码
    继承(子类复用父类)
       ↓
    父类加 virtual,子类加 override
       ↓
    CLR 为每个类生成 VTable
       ↓
    子类 VTable 复制父类,重写则替换方法地址
       ↓
    父类引用指向子类对象
       ↓
    运行时通过对象指针 → 找到 VTable → 执行正确方法
       ↓
    【多态实现】

    总结

  • 继承是多态的语法基础,让子类可以共享父类成员

  • 多态是父类引用指向子类对象,执行子类重写方法

  • VTable(虚方法表) 是 CLR 为类创建的方法地址数组,靠它实现运行时多态

  • 核心机制:子类复制父类 VTable → 重写替换方法地址 → 运行时查表调用

  • virtual/override 开启多态,new 不参与多态

相关推荐
波力海苔夹心脆6754 小时前
C# 序列化与反序列化详解:System.Text.Json、Newtonsoft.Json、XmlSerializer 用法、特性选项与安全实践
经验分享·后端·c#·json·.net
小羊没烦恼!9 小时前
在Scrum中实施敏捷建模
java·开发语言·windows·算法·c#
Lost of 程序猿10 小时前
建造者模式实战:告别“十参数构造函数“的数据导出任务
后端·设计模式·c#·asp.net
mudtools12 小时前
在.NET现有系统中快速集成飞书任务分配能力
后端·c#·.net
工具派15 小时前
Word文档太大怎么拆分?段落结构与两种拆法的边界实测
开发语言·c#·word
潜龙952715 小时前
需求文档一键变测试用例:手工用例智能生成平台
开发语言·c#
Lost of 程序猿15 小时前
命令模式实战:把“下单后的动作“打包成可执行的任务
后端·设计模式·c#·asp.net·命令模式
淡海水16 小时前
16-01-C#数据结构源码-附录A-术语表
unity·c#·游戏引擎·il2cpp
小羊没烦恼!16 小时前
【译】利用Asp.net MVC处理文件的上传下载
开发语言·缓存·c#·word·powerpoint·.net
波力海苔夹心脆67516 小时前
C# 海康威视摄像头二次开发入门:HCNetSDK 登录、实时预览、云台控制、录像与抓图(WinForms 实战)
开发语言·windows·经验分享·tcp/ip·c#