由剑指offer引发的思考——对象中虚函数指针的大小
2024-09-04 14:39:44
先看一个简单的问题:
一、定义一个空的类型,对于其对象我们sizeof其大小,是1字节。因为我们定义一个类型,编译器必须为其分配空间,具体分配多少是编译器决定,vs是1字节,分配在栈区。
那,这一个字节会被初始化吗?
举个例子:
#include<iostream>
class parent{ };
int main() {
parent my_par;
int a = 0;
std::cout << sizeof(my_par) << " "<< &my_par<<" "<<&a;
while (1);
return 0;
}
其输出:
我们查看内存,看得到都初始化为:CC CC CC CC
多调试几次,每次地址都不一样,但是内存值都是CC。为什么都是CC?
因为0xCC对应的是INT3断点,简单地说就是将要断下的指令地址处的第一个字节设置为0xCC,软件执行到0xCC(对应汇编指令INT3)时,会触发异常代码为EXCEPTION_BREAKPOINT的异常。这样我们的调试程序就能够接收到这个异常,然后进行相应的处理。具体.......所以,我们写的是异常代码,实际工作中空类型又有什么意义呢?具体会设计编译器逆向工程,有机会可以看看。
回到我们标题:
二、虚函数的问题
- 当类中声明虚函数时,编译器会在类中生成一个虚函数表,若子类自己有虚函数也会生成一个虚函数表;
- 虚函数表是一个存储 类的virtual成员函数指针的数据结构;
- 当存在虚函数时,每个对象都有一个指向虚函数表的指针(类本身没有指针,有一个编译器维护的虚函数表。对象有虚函数指针,我们sizeof是测的是对象所占内存);
- 若一个对象继承于两个都有虚函数的父类,他要维护两个虚函数指针;
- 虚函数指针存在于对象实例中最前面的位置;
#include <iostream>
using namespace std; class Base1{
virtual void fun1(){}
virtual void fun11(){}
public:
virtual ~Base1();
}; class Base2{
virtual void fun2(){}
}; class DerivedFromOne: public Base2
{
virtual void fun2(){}
virtual void fun22(){}
}; class DerivedFromTwo: public Base1, public Base2 //多继承
{
virtual void fun3(){}
}; void main()
{
Base2 my_base;
cout << "sizeof Base1 " << sizeof(Base1) << "输出vptb"<<(int*)*(int*)(&my_base)<< endl;//太复杂了,以后再说。
cout << "sizeof Base2" << sizeof(Base2) << endl;
cout << "sizeof FromOne " << sizeof(DerivedFromOne) << endl;
cout << "sizeof FromTwo " << sizeof(DerivedFromTwo) << endl;
system("pause")
}
输出:
可以看出:
1、每个单继承,对象都有一个vptr指针;多继承,对象就会有多个虚函数指针指向父类的虚函数表。虚函数表不占栈内存,由编译器维护,在代码区?我们测的是对象的内存。
2、Base2的对象的地址,就是vptr指向的虚函数表的地址,可以打开内存查看。这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。
最新文章
- elasticsearch常用的概念整理
- webpack中alias别名配置
- Linux的学习之路
- 读Lua游戏开发实践指南
- idea配置maven并添加镜像配置
- nodejs生成UID(唯一标识符)——node-uuid模块
- Hdu OJ 5115 Dire Wolf (2014ACM/ICPC亚洲区北京站) (动态规划-区间dp)
- redis的简单安装配置
- View (三) 视图绘制流程完全解析
- vim MiniBufExplorer 插件
- Flashback删除(闪回删除)
- Sql语句之select 5种查询
- python 读取图片的尺寸、分辨率
- IDEA破解 Intellij IDEA license server 激活(可用)
- Unity3d中如何查找一个脚本被挂在那些预设上面?
- 在Ubuntu14.04上配置jdk环境
- ansible常用命令大全
- Scala面向接口
- [转]sqlmap使用教程
- cad2016卸载/安装失败/如何彻底卸载清除干净cad2016注册表和文件的方法
热门文章
- httprunner(2)下载安装
- xxl-job之实现流程任务编排思路
- 【poj 2891】Strange Way to Express Integers(数论--拓展欧几里德 求解同余方程组 模版题)
- KMP——POJ-3461 Oulipo &;&; POJ-2752 Seek the Name, Seek the Fame &;&; POJ-2406 Power Strings &;&; POJ—1961 Period
- poj 3468A Simple Problem with Integers
- 2019牛客暑期多校训练营(第六场)J Upgrading Technology
- Bone Collector II HDU - 2639 01背包第k最大值
- 牛客编程巅峰赛S1第5场 - 青铜&;白银 B.完全平方数的尾巴 (暴力)
- (数据科学学习手札106)Python+Dash快速web应用开发——回调交互篇(下)
- python自动化运维之CMDB篇-大米哥