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

相关推荐
Ws_14 小时前
C#学习 Day2
开发语言·学习·c#
神仙别闹16 小时前
基于C#实现(WinForm)求解SIN(X)数值分析
c#
吴可可1231 天前
样条曲线转多段线技巧
算法·c#
影寂ldy1 天前
C#多维数组
开发语言·算法·c#
淡海水1 天前
01-认知篇-总览-HybridCLR是什么
unity·c#·aot·热更新·clr·hybrid
Xin_ye100861 天前
C# 零基础到精通教程 - 第十三章:文件与流 I/O——读写文件
开发语言·c#
xiaoshuaishuai81 天前
C# 服务注册与生命周期
开发语言·windows·c#
光泽雨1 天前
c#中特性的定义和IEnumerable<T>
c#
公子小六1 天前
基于.NET的Windows窗体编程之WinForms打印
windows·microsoft·c#·.net·winforms