首页 > 其他分享 >虚表与类的关系以及虚表的存放位置

虚表与类的关系以及虚表的存放位置

时间:2023-10-05 23:23:30浏览次数:38  
标签:obj 函数 位置 地址 存放 虚表 cout

总结:虚函数表是针对类的,一个类的所有对象的虚函数表都一样。

 

虚指针(vptr):每个含有虚方法(虚函数)对象里有虚表指针,指向虚表。

虚函数表:虚函数表是顺序存放虚函数地址的,虚表是顺序表,表里存放了虚函数的地址。

C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。目前gcc 和微软的编译器都是将vptr放在对象内存布局的最前面。

【代码示例】

#include <iostream>
using namespace std;

class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
virtual void h() { cout << "Base::h" << endl; }

};
typedef void(*Fun)(void);

int main()
{
Fun pFun = NULL;
Base obj_1,obj_2;
// obj_1 虚函数表 — 第一个函数
pFun = (Fun)*((int*)*(int*)(&obj_1));
pFun();
pFun = (Fun)*(((int*)*(int*)(&obj_1))+1);
pFun();
// 输出 虚函数表地址 与 虚函数表元素 的值
cout << "obj_1 虚函数表地址:" << (int*)(&obj_1) << endl;
cout << "obj_2 虚函数表地址:" << (int*)(&obj_2) << endl;
cout << "obj_1 虚函数表 — 第一个函数地址:" << (int*)*(int*)(&obj_1) << endl;
cout << "obj_2 虚函数表 — 第一个函数地址:" << (int*)*(int*)(&obj_2) << endl;
return 0;
}
/*
输出 :
Base::f
Base::g
obj_1 虚函数表地址:0018FF40
obj_2 虚函数表地址:0018FF3C
obj_1 虚函数表 — 第一个函数地址:0046F0AC
obj_2 虚函数表 — 第一个函数地址:0046F0AC
Press any key to continue
*/

【结论】

虚函数表属于类,类的所有对象共享这个类的虚函数表。
不同对象虚函数表是一样的(虚函数表的第一个函数地址相同);
每个对象内部都保存一个指向该类虚函数表的指针vptr,每个对象的vptr的存放地址都不一样,但是都指向同一虚函数表。

那么虚函数表存放在哪里呢?
虽然我们知道vptr指向虚函数表,那么虚函数表具体存放在内存哪个位置呢,虽然这里我们已经可以得到虚函数表的地址。实际上虚函数指针是在构造函数执行时初始化的,而虚函数表是存放在可执行文件中的。

下面的一篇博客测试了微软的编译器将虚函数表存放在了目标文件或者可执行文件的常量段中,http://blog.csdn.net/vicness/article/details/3962767

在gcc编译器的实现中虚函数表vtable存放在可执行文件的只读数据段.rodata中。

虚函数表vtable在Linux/Unix中存放在可执行文件的只读数据段中(rodata),这与微软的编译器将虚函数表存放在常量段存在一些差别。

参考自https://blog.csdn.net/w616589292/article/details/51250285

标签:obj,函数,位置,地址,存放,虚表,cout
From: https://www.cnblogs.com/Zhaolongtao/p/17744091.html

相关文章

  • 使用 expo-location 获取不到位置信息 Location.getCurrentPositionAsync() 结果无打
    问题描述:reactnative中使用expo-location获取位置信息时,按照官方文档执行案例,获取不到位置结果。Location.requestForegroundPermissionsAsync()执行后可以获取授权状态,但是执行到Location.getCurrentPositionAsync()时不会打印结果。解决方法:给Location.getCurrentPos......
  • 无涯教程-OC - 位置操作
    只要用户允许应用程序在核心位置框架的帮助下访问信息,无涯教程就可以在iOS中轻松找到用户的当前位置。位置处理步骤步骤1-创建一个基于View的简单应用程序。步骤2-选择您的项目文件,然后选择目标,然后添加CoreLocation.framework,如下所示-步骤3-在ViewController.xib中......
  • SAP ABAP 系统记录传输请求处理过程的日志存放目录
    /usr/sap/trans/log是SAP系统中的一个重要目录。这个目录下存放的文件主要是用来记录SAP系统在进行各种不同类型的传输请求(TransportRequest)处理过程中的操作日志。在SAP系统的日常运行和维护中,这些日志文件提供了很多有价值的信息,例如出现错误时,可以通过查看这些日志文件......
  • Destoon模板存放及调用规则
    一、模板存放及调用规则模板存放于系统template目录,template目录下的一个目录例如template/default/即为一套模板模板文件以.htm为扩展名,可直接存放于模板目录例如template/default/index.htm也可以存放于模板目录的子目录里例如template/default/member/index.htm在PHP......
  • 34. 在排序数组中查找元素的第一个和最后一个位置
    给你一个按照非递减顺序排列的整数数组nums,和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值target,返回[-1,-1]。你必须设计并实现时间复杂度为O(logn)的算法解决此问题。示例1:输入:nums=[5,7,7,8,8,10],target=8......
  • Oracle CloudWorld 2023:Safra Catz主题演讲——把客户的成功放在首要位置
    SafraCatz在OracleCloudWorld2023的开场演讲主题是“把客户的成功放在首要位置”。她强调了客户的重要性,并说大家通过合作和技术可以实现几乎一切。她感谢在场的观众,强调了学习和分享的重要性,以及公司致力于为客户提供更好服务的承诺。在演讲中,她还邀请了来自其他公司的高管......
  • 记录返回上一页滚动条的位置
    scrollBehavior可以记录滚动条位置,也可以自己设定滚动条位置constrouter=createRouter({//createRouter返回一个router实例history:createWebHistory(),scrollBehavior:(to,from,savePosition)=>{if(savePosition){returnsavePosition;......
  • ansible教程:使用win_shell和win_copy从 HTTP 文件服务器下载文件并将其复制到目标位置
    with_fileglob参数无法直接指定HTTP文件服务器上的文件路径。它是用于在本地文件系统中进行文件的模式匹配,并将匹配的文件作为迭代项来执行任务。如果你需要从HTTP文件服务器上下载文件并将其复制到目标位置,你可以使用适当的工具或库来实现这个任务。下面是一个示例,使用curl......
  • 如何查找链接库的位置,编译和执行时分别?
    GCC动态链接库链接查找https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.htmlItlooksintheDT_RPATHsectionoftheexecutable,unlessthereisaDT_RUNPATHsection.ItlooksinLD_LIBRARY_PATH.Thisisskippediftheexecutableissetuid/se......
  • xxl-job的任务失败重试位置
    从两个点说明,一是失败的任务是如何记录到数据库,而是如何从数据拿错误日志进行重试的第一点,任务失败后调用接口@RequestMapping("/trigger")最终到这里 privatestaticvoidprocessTrigger(XxlJobGroupgroup,XxlJobInfojobInfo,intfinalFailRetryCount,Trigg......