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 不参与多态

相关推荐
2601_9620725511 小时前
李梦娇常识4600问|题库|打印版
sql·华为od·华为·c#·华为云·.net·harmonyos
m0_5474866613 小时前
《C#语言程序设计与实践》 全套PPT课件
c语言·c#·c语言程序设计
叶帆14 小时前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
IT方大同15 小时前
(嵌入式操作系统)信号量
嵌入式硬件·c#
z落落15 小时前
C# FileStream文件流读取文件
开发语言·c#
yngsqq16 小时前
排版优化 异形排版
c#
苦学的罐头16 小时前
C# 协变与逆变深度解析:为什么 IEnumerable<T> 能转换,而 List<T> 不行?
开发语言·c#·list
FuckPatience17 小时前
使用ReactiveUI 前端绑定不生效
c#
天天代码码天天17 小时前
用 TensorRT 加速 PP-OCR:一套 C++ DLL + C# 调用的高性能 OCR 推理方案
c++·c#·ocr