当前位置: 首页 > news >正文

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

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

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

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

二、基础概念快速回顾

1. 继承 (Inheritance)
  • 一个类(子类 / 派生类)可以复用另一个类(父类 / 基类)的字段、属性、方法
  • 关键字::
  • 单继承:一个类只能有一个直接父类
    // 父类 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:也能实现多态(原理一致)

多态代码示例

// 父类:标记虚方法 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("喵喵喵"); } }

多态核心用法

// 父类引用 指向 子类对象 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

[0]:Animal.Speak()

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

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

③ 子类 Cat VTable

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

当你执行:

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普通实例方法、静态方法不进虚方法表
    继承(子类复用父类) ↓ 父类加 virtual,子类加 override ↓ CLR 为每个类生成 VTable ↓ 子类 VTable 复制父类,重写则替换方法地址 ↓ 父类引用指向子类对象 ↓ 运行时通过对象指针 → 找到 VTable → 执行正确方法 ↓ 【多态实现】

    总结

  • 继承是多态的语法基础,让子类可以共享父类成员
  • 多态是父类引用指向子类对象,执行子类重写方法
  • VTable(虚方法表)是 CLR 为类创建的方法地址数组,靠它实现运行时多态
  • 核心机制:子类复制父类 VTable → 重写替换方法地址 → 运行时查表调用
  • virtual/override开启多态,new不参与多态
http://www.jsqmd.com/news/759812/

相关文章:

  • 保姆级教程:在Ubuntu 22.04上搞定llama.cpp的GPU加速(CUDA 12.2 + cuBLAS)
  • 选上门家教机构不光看价格:湖南师大家教中心晒出自己的“教师准入门槛 - 教育快讯速递
  • Geniatech DB982开发板:8K智能电视硬件与优化指南
  • Claude 4.6 Opus手把手教程:万字长文+深度推理,2026百度SEO与GEO实战
  • ThinkPad风扇终极控制指南:如何用TPFanCtrl2彻底告别风扇噪音和散热烦恼
  • DOS命令没你想的那么难:10个实用命令搞定日常文件管理与系统维护
  • Nodejs服务如何无缝接入多模型并实现自动降级
  • 如何高效将3D模型转换为Minecraft结构:ObjToSchematic专业指南
  • 从‘伊拉克成色’二手AEM FIC6起步:我的八代思域涡轮改装自学调校心路历程
  • 别再傻傻分不清了!Java Map里compute、putIfAbsent这几个方法,我画了张图帮你搞定
  • 使用Nodejs和Taotoken为网站构建实时AI客服后端
  • 【Java函数性能优化黄金法则】:20年架构师亲授7个被90%开发者忽略的JVM级优化技巧
  • 免费Claude-3 API代理服务:原理、配置与实战指南
  • ESP32开发环境搭建:手把手教你解决VSCode中编译器路径报错(附c_cpp_properties.json配置)
  • Arm系统寄存器与SME特性解析及陷阱机制
  • 如何用LeRobot在5分钟内搭建你的第一个AI机器人控制系统?
  • 在 Node.js 后端服务中接入 Taotoken 实现智能客服会话
  • 2026年湖南GEO优化TOP5服务商榜单|企业AI时代获客选型必读 - 星城方舟
  • AI结对编程:让快马平台优化你的前端图片画廊性能与代码
  • R 4.5空间扩展生态剧变:tidyverse地理栈全面重构,dplyr 1.1.0+空间谓词下推原理与11个真实GIS项目迁移实录
  • Python 实时监控 A 股行情并自动筛选强势股(REST + WebSocket 两种方案)
  • 实战指南:基于快马平台为微服务集群构建openclaw滚动更新方案
  • Windows任务栏透明美化终极教程:3种专业级效果轻松实现
  • WarcraftHelper:魔兽争霸III现代化增强插件完全使用手册
  • stm32 启动文件startup_stm32f103xe.s的内容
  • 告别手动配置:WinUtil 一键完成Windows系统优化与软件部署
  • 将 Claude Code 编程助手对接至 Taotoken 的详细配置步骤解析
  • 告别CentOS后,我为什么选择Rocky Linux 9.3作为我的主力开发环境?
  • 深入探索PCL启动器:打造高效Minecraft游戏入口的技术内幕
  • 硬件性能突破:AMD Ryzen调试工具如何实现85%系统稳定性提升