当前位置: 首页 > 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.lqws.cn/news/166267.html

相关文章:

  • 【如何做好应用架构?】
  • YOLOv11 | 注意力机制篇 | 混合局部通道注意力MLCA与C2PSA机制
  • CMake指令:add_definitions
  • 06.最长连续序列
  • 是否存在路径(FIFOBB算法)
  • Java-IO流之缓冲流详解
  • 实现基于Yolo的异常聚集算法
  • 经典算法:回文链表
  • 计算机操作系统知识点总结④【完】
  • 2025年渗透测试面试题总结-ali 春招内推电话1面(题目+回答)
  • linux应急响应检查脚本
  • web第十次课后作业--Mybatis的增删改查
  • Java常用工具类方法详解及使用案例
  • ABP VNext 在 Kubernetes 中的零停机蓝绿发布
  • 用 NGINX 构建高效 POP3 代理`ngx_mail_pop3_module`
  • 计算机组成原理(计算篇)
  • 在MATLAB中使用自定义的ROS2消息
  • 本地部署大模型实战:使用AIStarter一键安装Ollama+OpenWeb教程(含最新版本更新指南)
  • 【python深度学习】Day 45 Tensorboard使用介绍
  • 主流消息队列对比
  • 基于protobuf + iceoryx实现共享内存上的零拷贝
  • vue和uniapp聊天页面右侧滚动条自动到底部
  • python执行测试用例,allure报乱码且未成功生成报告
  • 学习路之PHP--webman安装及使用、webman/admin安装
  • Mobile App UI自动化locator
  • Jenkins | Jenkins构建成功服务进程关闭问题
  • Redis数据持久化机制深度解析
  • 从零开始的嵌入式学习day33
  • 【Fifty Project - D33】
  • select、poll、epoll 与 Reactor 模式