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

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.dtcms.com/a/326384.html

相关文章:

  • # Java制作堆Dump
  • 学习观察和行动:机器人操作中任务-觉察的视图规划
  • 如何解决 JetBrains IntelliJ IDEA 2024.2 和 2025.2 新版本区域选择问题:key is invalid
  • 【后端】struct.pack()
  • 【昇腾】Atlas 500 A2智能小站M.2 SATA盘启动Ubuntu22.04系统CPU占用过高问题处理_20250811
  • Qt-信号和槽
  • Android16新特性速记
  • Python day 41
  • [langchian]使用langchain构建一个chatbot
  • JS深拷贝 浅拷贝、CSS垂直水平居中
  • CRM(客户关系管理)框架详解
  • 【09-神经网络介绍2】
  • 快速了解TF-IDF算法
  • 高精度蓝牙定位:技术、应用与未来发展
  • AI Copilot
  • istio如何采集method、url指标
  • Linux系统编程Day12 -- 环境变量(初识)
  • [特殊字符][特殊字符][特殊字符]【Maven】pom依赖的版本推荐与依赖冲突问题
  • C#使用EPPlus读写Excel
  • 定制化4G专网架构,满足多行业专属需求
  • 在线代码比对工具
  • HTML5中华美食网站源码
  • 布控球:临时布防场景的高清回传利器-伟博
  • 双椒派™ E2000D 开发板深度解析
  • 【Altium designer】一键添加多个器件参数的“备注”
  • conda一键配置python开发环境
  • echarts 柱状图堆叠踩坑指南 (已解决)
  • 读《精益数据分析》:媒体内容平台全链路梳理
  • 超算中心的机器上怎么部署Linux的?
  • 3.6 修改vuex的状态Mutations ,Actions