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

C++多态是如何实现

📄问题

C++多态是如何实现

📝我的回答

C++中的多态主要分为两种:编译时多态(静态多态)和运行时多态(动态多态)。其中运行时多态是我们通常讨论的重点,它是通过虚函数机制实现的。

运行时多态的核心机制是虚函数表(vtable)和虚表指针(vptr)。当一个类定义了虚函数,编译器会为这个类创建一个虚函数表,表中存储了该类所有虚函数的地址。同时,编译器会在每个包含虚函数的类的对象中插入一个隐藏的指针(vptr),指向该类的虚函数表。

具体实现过程如下:

当我们定义一个包含虚函数的类时,编译器会为这个类创建一个虚函数表(vtable)。

类的每个对象都会包含一个虚表指针(vptr),通常位于对象内存布局的开始位置。

当派生类重写基类的虚函数时,派生类的虚函数表中对应的函数指针会被更新为派生类的函数实现。

当我们通过基类指针或引用调用虚函数时,程序会先找到对象的vptr,通过vptr找到虚函数表,然后在表中查找对应的函数地址,最后调用该函数。

这个过程可以用代码和内存布局来说明:

class Base {
public:virtual void func1() { std::cout << "Base::func1" << std::endl; }virtual void func2() { std::cout << "Base::func2" << std::endl; }void nonVirtual() { std::cout << "Base::nonVirtual" << std::endl; }
};class Derived : public Base {
public:void func1() override { std::cout << "Derived::func1" << std::endl; }// func2未重写,使用Base::func2
};int main() {Base* ptr = new Derived();ptr->func1();  // 调用Derived::func1ptr->func2();  // 调用Base::func2delete ptr;
}

内存布局大致如下:

+--------+
| vptr   | --> Base vtable: [&Base::func1, &Base::func2]
+--------+
| 其他成员 |
+--------+

Derived对象的内存布局:

+--------+
| vptr   | --> Derived vtable: [&Derived::func1, &Base::func2]
+--------+
| 继承的成员|
+--------+
| 新增成员 |
+--------+

当执行ptr->func1()时,实际的调用过程是:获取ptr指向的对象的vptr,通过vptr找到对应的虚函数表,在表中查找func1的地址(通常是表中的第一个条目),调用该地址处的函数,这就是为什么即使ptr是Base*类型,调用的仍然是Derived::func1。

值得注意的是,虚函数机制会带来一些运行时开销:每个对象增加了vptr的内存开销(通常是一个指针的大小,32位系统4字节,64位系统8字节),每个类需要维护一个虚函数表,调用虚函数时需要额外的间接寻址,此外,C++的多重继承会使虚函数的实现更复杂,可能涉及到多个虚表和复杂的指针调整。

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

相关文章:

  • 【Altium designer】解决报错“Access violation at address...“
  • 机器学习第九课之DBSCAN算法
  • 【接口自动化测试】---YAML、JSON Schema
  • 02Vue3
  • github上传项目
  • 视频前处理技术全解析:从基础到前沿
  • Elasticsearch 官方 Node.js 从零到生产
  • docker安装Engine stopped
  • AVS Video Converter视频转换与编辑工具深度评测
  • 功能、延迟、部署、成本全解析:本地化音视频 SDK 对比 云端方案
  • Go 多进程编程-socket(套接字)
  • 定制化4G专网架构,满足多行业专属需求
  • 区间修改 - 差分
  • Kubernetes部署apisix的理论与最佳实践(一)
  • npm install报错~[master] npm install npm error code ERESOLVE npm err
  • 大数据系统架构模式:驾驭海量数据的工程范式
  • RabbitMQ 消息转换器详解
  • 心理咨询|学生心理咨询评估系统|基于Springboot的学生心理咨询评估系统设计与实现(源码+数据库+文档)
  • 使用TextureView和MediaPlayer播放视频黑屏问题
  • AI模型服务接入WAF防火墙
  • 【C++】哈希表的实现(unordered_map和unordered_set的底层)
  • DDIA第五章:分布式数据复制中的一致性与冲突处理
  • 触想定制化工业一体机化身渔业预警终端,守望渔船安全
  • Spring Boot 菜单删除功能的实现与事务管理
  • 【前端基础】16、结构伪类(注:粗略说明)
  • 数据上云有什么好处?企业数据如何上云?
  • 基于FPGA的热电偶测温数据采集系统,替代NI的产品(一)FPGA 测温研究现状
  • 自由学习记录(81)
  • 【JAVA】使用系统音频设置播放音频
  • 零 shot 语义+在线闭环:深度学习让机器人学会“主动”