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

C++虚函数表(虚表Virtual Table,简称vtable、VFT)(编译器为支持运行时多态(动态绑定)而自动生成的一种内部数据结构)虚函数指针vptr

文章目录

      • **1. 虚函数表的核心概念**
        • - **虚函数表(vtable)**:
        • - **虚函数指针(vptr)**:
      • **2. 虚函数表的生成与工作流程**
        • **生成时机**
          • - **当一个类中至少有一个虚函数时**,编译器会为该类生成一个虚函数表。
          • - **派生类继承虚函数表**:
        • **调用流程**
          • 1. **对象创建时**:
          • 2. **调用虚函数时**:
      • **3. 示例代码解析**
        • - 以下代码展示了虚函数表的工作原理
        • - **虚函数表的生成**:
        • - **调用过程**:
      • **4. 虚函数表的内存布局**
        • - 以一个简单的类为例
        • - **对象内存布局**:
        • - **虚函数表结构**:
      • **5. 虚函数表的注意事项**
        • 1. **性能开销**:
        • 2. **纯虚函数与抽象类**:
        • 3. **多继承与虚函数表**:
        • 4. **编译器相关**:
      • **6. 虚函数调用流程图**
      • **7. 总结**

C++中的 虚函数表(Virtual Table,简称 vtable)是编译器为支持 运行时多态(动态绑定)而自动生成的一种内部数据结构。它的核心作用是通过 虚函数指针(vptr)和虚函数表的配合,实现基类指针或引用调用派生类重写函数的能力。


1. 虚函数表的核心概念

- 虚函数表(vtable)

每个包含虚函数的类都会有一个虚函数表。这个表是一个指针数组,存储了该类所有虚函数的地址。例如:

  • 如果一个类有3个虚函数,虚函数表就包含3个指针,分别指向这3个函数的实现。
  • 如果派生类重写了某个虚函数,派生类虚函数表中对应位置的指针会被替换为派生类的函数地址。
- 虚函数指针(vptr)

每个包含虚函数的对象在内存中会隐式地包含一个指针(vptr),指向该对象所属类的虚函数表。

  • vptr通常位于对象内存布局的最前面(具体位置可能因编译器而异)。
  • 当通过基类指针或引用调用虚函数时,程序会通过vptr查找虚函数表,找到正确的函数地址并执行。

2. 虚函数表的生成与工作流程

生成时机
- 当一个类中至少有一个虚函数时,编译器会为该类生成一个虚函数表。
- 派生类继承虚函数表
  • 如果派生类没有重写基类的虚函数,则虚函数表中直接继承基类的虚函数地址。
  • 如果派生类重写了某个虚函数,则虚函数表中对应位置的指针会被更新为派生类的函数地址。
调用流程
1. 对象创建时

编译器会自动初始化对象的vptr,使其指向该类的虚函数表。

2. 调用虚函数时
  • 程序通过对象的vptr找到虚函数表。
  • 根据虚函数表中的索引(与函数声明顺序一致)找到对应的函数地址。
  • 调用该地址指向的函数(可能是基类或派生类的实现)。

3. 示例代码解析

- 以下代码展示了虚函数表的工作原理
#include <iostream>
using namespace std;class Base {
public:virtual void func() { cout << "Base::func()" << endl; }
};class Derived : public Base {
public:void func() override { cout << "Derived::func()" << endl; }
};int main() {Base* ptr = new Derived();ptr->func();  // 输出 "Derived::func()"delete ptr;return 0;
}
- 虚函数表的生成
  • Base类有一个虚函数func(),因此编译器为Base生成一个虚函数表,表中存储Base::func()的地址。
  • Derived类重写了func(),因此编译器为Derived生成一个新的虚函数表,表中存储Derived::func()的地址。
- 调用过程
  • ptrBase*类型,但指向Derived对象。
  • 调用ptr->func()时,程序通过Derived对象的vptr找到Derived的虚函数表,调用Derived::func()

4. 虚函数表的内存布局

- 以一个简单的类为例
class Base {
public:virtual void func1() {}virtual void func2() {}
};
- 对象内存布局

每个Base对象的内存布局如下:

[vptr] -> 指向Base的虚函数表
[其他成员变量]
Base
+virtual void func1()
+virtual void func2()
«data»
BaseObject
vptr --> Base
data1: int
data2: double
- 虚函数表结构
Base的虚函数表:
+-----------------+
| func1() 的地址  |
+-----------------+
| func2() 的地址  |
+-----------------+
Base的虚函数表
func1() 地址
func2() 地址

5. 虚函数表的注意事项

1. 性能开销
  • 调用虚函数需要通过两次间接寻址(vptr → 虚函数表 → 函数地址),比直接调用普通函数稍慢。
  • 每个对象需要额外存储一个vptr,增加了内存占用。
2. 纯虚函数与抽象类
  • 如果类中包含纯虚函数(virtual void func() = 0;),则该类为抽象类,不能实例化对象。
  • 纯虚函数在虚函数表中通常用特殊标记(如NULL)表示。
3. 多继承与虚函数表
  • 多继承情况下,对象可能包含多个vptr,分别指向不同基类的虚函数表。
  • 虚函数表的管理会更复杂,但核心原理与单继承相同。
Derived对象
vptr1 (Base1)
vptr2 (Base2)
Base1::func()
Base2::func()
4. 编译器相关
  • 虚函数表是编译器的实现细节,C++标准未规定具体实现方式。主流编译器(如GCC、MSVC)均采用类似机制。

6. 虚函数调用流程图

以下是虚函数调用的完整流程:

Base* ptr = new Derived();
ptr->func()
vptr 指向 Derived 的虚函数表?
查找虚函数表中 func() 的地址
调用 Derived::func()
查找虚函数表中 func() 的地址
调用 Base::func()

7. 总结

虚函数表是C++实现运行时多态的核心机制。通过虚函数表和虚函数指针的配合,C++能够在运行时根据对象的实际类型动态选择正确的函数实现。这种机制虽然带来了一定的性能和内存开销,但极大地增强了代码的灵活性和可扩展性,是面向对象编程中多态特性的基石。

http://www.xdnf.cn/news/882343.html

相关文章:

  • 关于akka官方quickstart示例程序(scala)的记录
  • 【C++项目】负载均衡在线OJ系统-2
  • 解构与重构:PLM 系统如何从管理工具进化为创新操作系统?
  • 通过Chain Prompts方式将LLM的能力引入测试平台:正交实验测试用例生成
  • 多模态大语言模型arxiv论文略读(109)
  • 计算机基础知识(第四篇)
  • Apache Doris + MCP:Agent 时代的实时数据分析底座
  • Ntfs!ReadIndexBuffer函数分析之nt!CcGetVirtualAddress函数之nt!CcGetVacbMiss
  • 如何在电脑上轻松访问 iPhone 文件
  • 斐波那契数列------矩阵幂法
  • 【Python3教程】Python3基础篇之错误和异常
  • Python语法进阶篇 --- 封装、继承、多态、静态方法、类方法
  • 嵌入式学习Day33
  • 如何更快的提升项目的开发进度
  • 从 ClickHouse、Druid、Kylin 到 Doris:网易云音乐 PB 级实时分析平台降本增效
  • 【SSM】SpringBoot笔记2:整合Junit、MyBatis
  • XHR / Fetch / Axios 请求的取消请求与请求重试
  • JVM——如何打造一个类加载器?
  • NLP驱动网页数据分类与抽取实战
  • 「深度拆解」Spring Boot如何用DeepSeek重构MCP通信层?从线程模型到分布式推理的架构进化
  • 自动驾驶+人形机器人?亚马逊即将测试人形机器人送货
  • 元素 “cas:serviceResponse“ 的前缀 “cas“ 未绑定
  • 使用ReactNative加载Svga动画支持三端【Android/IOS/Harmony】
  • StarRocks
  • Spring Boot + OpenAI 构建基于RAG的智能问答系统
  • Java 抗量子算法:构建后量子时代的安全基石
  • 系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
  • 接IT方案编写(PPT/WORD)、业务架构设计、投标任务
  • 为什么要选择VR看房?VR看房有什么优点?
  • 大陆4D毫米波雷达ARS548调试