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

C++虚函数与类对象模型深度解析

目录

1. 引言

2. 单继承下的虚函数表

2.1 基本概念

2.2 示例分析

3. 多重继承下的虚函数表

3.1 基本概念

3.2 示例分析

4. 虚函数表指针(vptr)的存储

4.1 单继承

4.2 多重继承

5. 常见面试题解析

问题1:D 继承 B1 和 B2,D 新增虚函数放在哪里?

问题2:D 有几个虚表指针?

问题3:如果 B1 没有虚函数,B2 有虚函数

6. 总结


1. 引言

在C++中,虚函数是实现运行时多态(动态绑定)的核心机制,而虚函数表(vtable)和虚表指针(vptr)是实现这一机制的关键。理解虚函数在类对象模型中的存储方式,对于深入掌握C++面向对象编程至关重要。本文将详细分析:

  • 单继承下的虚函数表布局
  • 多重继承下的虚函数表布局
  • 虚函数表指针(vptr)的存储方式
  • 新增虚函数对虚表的影响

2. 单继承下的虚函数表

2.1 基本概念

当一个类包含虚函数时,编译器会为该类生成一个虚函数表(vtable),存储所有虚函数的地址。每个对象的内存布局中,前4字节(32位系统)或前8字节(64位系统)存储指向虚函数表的指针(vptr)。

2.2 示例分析

class A {
public:virtual void func1() { cout << "A::func1" << endl; }virtual void func2() { cout << "A::func2" << endl; }
};class B : public A {
public:virtual void func1() override { cout << "B::func1" << endl; } // 重写virtual void func3() { cout << "B::func3" << endl; }          // 新增
};

内存布局:

对象虚表指针(vptr)虚表内容
Avptr_AA::func1A::func2
Bvptr_BB::func1(重写), A::func2B::func3(新增)

关键点:

  • B 继承 A,因此 B 的虚表包含 A 的所有虚函数(func1 被重写,func2 保留)。
  • B 新增的 func3 附加到虚表末尾。

3. 多重继承下的虚函数表

3.1 基本概念

在多重继承中,派生类会为每个包含虚函数的基类维护一个独立的虚函数表。如果派生类新增虚函数,它们会附加到第一个基类的虚表末尾

3.2 示例分析

class B1 {
public:virtual void f1() { cout << "B1::f1" << endl; }
};class B2 {
public:virtual void f2() { cout << "B2::f2" << endl; }
};class D : public B1, public B2 {
public:virtual void f1() override { cout << "D::f1" << endl; }  // 重写 B1::f1virtual void f2() override { cout << "D::f2" << endl; }  // 重写 B2::f2virtual void f3() { cout << "D::f3" << endl; }           // 新增虚函数
};

内存布局:

对象虚表指针(vptr)虚表内容
Dvptr_B1D::f1D::f3(新增)
vptr_B2D::f2

关键点:

  • D 继承 B1 和 B2,因此有 2 个虚表指针vptr_B1 和 vptr_B2)。
  • D 新增的 f3 附加到 B1 的虚表末尾(因为 B1 是第一个基类)。
  • B2 的虚表仅存储 D 重写的 f2

4. 虚函数表指针(vptr)的存储

4.1 单继承

  • 只有一个 vptr,位于对象起始地址。
  • 示例:
A a;
B b;
cout << *(void**)&a; // 输出 A 的虚表地址
cout << *(void**)&b; // 输出 B 的虚表地址

4.2 多重继承

  • 每个基类对应一个 vptr,按继承顺序排列。
  • 示例:
D d;
void** vptr1 = *(void***)&d;                     // B1 的 vptr
void** vptr2 = *(void***)((char*)&d + sizeof(B1)); // B2 的 vptr

5. 常见面试题解析

问题1:D 继承 B1 和 B2D 新增虚函数放在哪里?

答案:放在第一个基类 B1 的虚表末尾。

问题2:D 有几个虚表指针?

答案:2 个(对应 B1B2)。

问题3:如果 B1 没有虚函数,B2 有虚函数

6. 总结

继承方式虚表指针数量新增虚函数存储位置
单继承1附加到基类虚表末尾
多重继承等于基类数量附加到第一个基类虚表末尾

关键结论:

  1. 虚函数表(vtable)是实现动态绑定的核心。
  2. 单继承时,派生类虚表包含基类虚函数 + 新增虚函数。
  3. 多重继承时,派生类为每个基类维护独立虚表,新增虚函数放在第一个基类虚表末尾。

相关文章:

  • binlog 解析工具——my2sql
  • 使用JSP踩过的坑
  • Double使用注意事项
  • 【编程实践】利用open3d对点云进行聚类并可视化
  • Kotlin IR编译器插件开发指南
  • 互联网大厂Java求职面试:短视频平台大规模实时互动系统架构设计
  • Eigen 库实现最小二乘算法(Least Squares)
  • Unity基础学习(九)Resources资源同步与异步加载
  • 如何在 Linux 系统中永久禁用交换分区 ?
  • 实验绘图参考-0525版(自用)
  • PostgreSQL 与 MongoDB:为您的数据项目选择合适的数据库
  • 记录第一次正式收到SCI期刊论文的审稿
  • Ubantu22.04离线安装、卸载mysql8.0.39并设置开机自启
  • 深入理解 Linux 的 set、env 和 printenv 命令
  • 使用粘滞键修改windows密码
  • 医学写作供应商管理全流程优化
  • 前端课设Web2
  • 微服务——网关
  • 第九章 云平台开发
  • 测试工程师如何通俗理解和入门RAG:从“查资料”到“写答案”的智能升级
  • 太原优化型网站建设/百度seo网络营销书
  • php网站的开发环境/网络推广营销网站建设专家
  • 企业文化宣传册模板/盛大游戏优化大师
  • 长沙 直播网站建设/seo技术学院
  • 广告公司怎么取名字/关键词首页优化
  • 贵阳快速建站模板/最新搜索关键词