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

相关推荐
月昤昽4 小时前
autocad二次开发 3.阵列与面域
c#·二次开发·autocad二次开发
唐青枫7 小时前
别只会用 MemoryCache!C#.NET CacheManager 详解:多级缓存、Region 与 Redis 实战
c#·.net
吴可可1238 小时前
PointF坐标精度与使用注意事项
c#
鸽子一号10 小时前
c#Modbus通信
开发语言·c#
cjp56013 小时前
001.Blazor简介
c#
工程师00714 小时前
C# 程序集、IL、CLR 执行流程
c#·clr·il·程序集
xxjj998a14 小时前
PHP vs C#:核心差异全解析
开发语言·c#·php
我不在你不在15 小时前
C# 异步与LINQ实战亮点
c#
游乐码15 小时前
c#预处理器指令
c#