类中成员函数的调用机制

C++中成员函数(无论是否为虚函数)的调用机制都涉及到this指针的使用,但虚函数的存在引入了虚函数表(vtable),这改变了函数调用的具体实现方式。下面详细解释没有虚函数和有虚函数时成员函数调用的差异:

没有虚函数时的成员函数调用

当一个类没有虚函数时,所有成员函数调用都是静态绑定的,即编译器在编译时就能确定调用哪个函数。这种情况下:

  • this指针 :每个成员函数都隐式地接收一个指向调用对象的this指针。这允许成员函数访问和操作调用它的对象的数据成员。
  • 函数地址:编译器在编译时根据函数的定义解析函数的地址,并直接将这个地址硬编码到调用指令中。调用成员函数时,程序直接跳转到这个地址执行函数代码。

有虚函数时的成员函数调用

当类中包含虚函数时,需要支持运行时多态,即根据对象的实际类型在运行时确定调用哪个函数。这种情况下的调用机制如下:

  • 虚函数表(vtable):每个包含虚函数的类都有一个虚函数表,这是一个包含函数指针的数组,指向类中所有虚函数的实现。
  • 虚函数表指针(vptr):每个对象都包含一个指向其类的虚函数表的指针(vptr)。这个指针是对象内存布局的一部分,通常位于对象数据的开始位置。
  • 调用过程 :
    1. 通过对象的this指针访问对象的内存。
    2. 使用this指针找到对象中的vptr。
    3. 通过vptr访问虚函数表,然后根据需要调用的虚函数在表中的位置找到对应的函数指针。
    4. 跟随这个函数指针跳转到相应的函数实现,执行函数代码。

这个机制允许在派生类中重写虚函数,并在运行时根据对象的实际类型调用相应的函数实现,支持了多态性。

总结

  • 没有虚函数时:函数调用是静态绑定的,调用地址在编译时就已确定,直接通过硬编码的地址调用。
  • 有虚函数时:引入虚函数表以支持运行时多态,函数调用通过动态查找虚函数表实现,根据对象的实际类型动态调用相应的函数。

所以静态绑定,实现直接根据函数名称确定函数地址进行调用,并隐式传入了this指针,故成员函数可以访问当前对象的数据,而动态绑定需要先通过当前对象this的指针,找的虚函数表指针,然后再定位到具体的函数地址,进行函数的调用,并且虚函数的调用时任然会隐式的传入this指针,实现对当前对象数据的访问。

这两种机制反映了C++设计中对效率和灵活性的不同需求的平衡。

类的内存布局

当基类中没有定义虚函数时,其长度=数据成员长度;派生类长度=自身数据成员长度+基类继承的数据成员长度;

当基类中定义虚函数后,其长度=数据成员长度+虚函数表的地址长度;派生类长度=自身数据成员长度+基类继承的数据成员长度+虚函数表的地址长度。

相关推荐
akinggw1 小时前
libsherpacore - 基于 sherpa-onnx 的 C++ 语音交互静态库
c++·交互·语音识别
xiaoye-duck1 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(中):全量响应实现和测试
网络·c++·语言模型·chatgpt
東隅已逝,桑榆非晚2 小时前
算法3.双指针法-快乐数
c++·笔记·学习·算法
eggwyw3 小时前
C++相交链表和反转链表详解
开发语言·c++
杜 硕3 小时前
从零开始的C++生活——第六讲——02
c++·算法·生活
小超人诞生日记3 小时前
C++ STL 反向迭代器:从源码框架到适配器实现
c++·算法
青少儿编程课堂3 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会Scratch考级:校园成语接龙大挑战解析
c++·python·算法·bfs·信息学竞赛
小贾要学习3 小时前
【C++后端开发项目】Reactor 模型 / C++ 仿写 muduo HTTP 服务器:让底层网络库真正跑起网页
linux·服务器·c++·http·网络编程·muduo·reactor模型
A7bert7774 小时前
【MobileSAM部署至RK3588】环境适配→转换RKNN→开发板部署
c++·人工智能·深度学习·目标检测·ubuntu
青少儿编程课堂4 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会C/C++考级:分层图最短路解析
c++·python·算法·bfs·信息学竞赛