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

相关推荐
用户37215742613514 小时前
C# 实现 Excel 单元格保护:锁定公式并允许编辑指定区域
c#·ai编程·编程语言
公子小六19 小时前
基于.NET的Windows窗体编程之WinForms数据持久化(1)
windows·microsoft·c#·.net·winforms
三雷科技20 小时前
第6章第4节:自定义分词器
开发语言·c#
zhanghaha131421 小时前
C# 系列教程_12 字符串 string 保姆级系统教程(面向新手,大量示例 + 原理讲解)
开发语言·数据库·c#
Coder_Shenshen2 天前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
寂寞的船2 天前
【Unity知识速递】第10期 Unity GC 零分配实战:从 UnityEngine.Pool 到手动 GC 控制的全链路优化
jvm·unity·c#·游戏引擎·lucene
1-1=02 天前
C# 数据结构和特殊类型
数据结构·c#·.net·.netcore
波力海苔夹心脆6754 天前
C# WPF 资源字典详解:ResourceDictionary、MergedDictionaries 与自定义控件案例
开发语言·c#·wpf·入门教程·resource·资源字典
AI导出鸭PC端4 天前
Perplexity批量导出没有PDF模式?AI导出鸭插件补上最后一块拼图
人工智能·pdf·c#·ai导出鸭
Risehuxyc4 天前
C# 选用更流行的语言版本
c#