《深度探索C++对象模型》调用虚函数
如果一个类有虚函数,那么这个类的虚函数会被放在一个虚函数表里面, 使用这个类声明的对象中,会有一个指向虚函数表的指针,当使用指向 这个对象的指针或者这个对象的引用调用一个虚函数的时候,就会从虚函数表中去 查找该函数,然后对其进行调用。
如果有如下的类:
class A {
public :
int m_a;
A() {}
~A() {} virtual void test() { cout << "A info : " << __LINE__ << " , " << __func__ << endl;}
}; class B : public A{
public :
int m_b;
B() {}
~B() {} virtual void test() { cout << "B info : " << __LINE__ << " , " << __func__ << endl;}
};
那么我们显示出一个 B 类对象的内存状态, 这个类声明的对象的内存布局会是下面这样:
#ifdef __x86_64__
cout << "__x86_64__" << endl;
#else
cout << "not 64" << endl;
#endif cout << "sizeof(B) = " << sizeof(B) << endl;
cout << "sizeof(int) = " << sizeof(int) << endl; B b;
b.m_a = 0x01010101;
b.m_b = 0x02020202; show_mem(&b, sizeof(b));
执行结果:
__x86_64__
sizeof(B) =
sizeof(int) =
addrress : f8 cc fa ff 7f
memory layout : 0f
我们看到,拥有两个 int 成员变量的 b 对象,它占用的内存大小却不是 两个 sizeof(int) 的和 8,而是16。很明显,另外8个字节就是存放虚函数表地址 的了,因为目前使用的是64位系统,指针占用的空间是64 bit。
那么,我们现在知道了一个对象的内存布局后,就可以采取 "非法" 手段 调用一个虚函数了。比如下面这段代码:
#ifdef __x86_64__
typedef unsigned long int POINT_SIZE;
#else
typedef int POINT_SIZE;
#endif typedef void(*Fun)(); //获取对象的地址
POINT_SIZE *po = (POINT_SIZE *)&b; //获取这个对象前 8 个字节的值,这个值是虚函数表的地址
POINT_SIZE tbl = po[]; //把这个值转换为地址类型,也就是虚函数表的地址
POINT_SIZE *ptbl = (POINT_SIZE *)tbl; int pos = ;
//虚函数表的第一表项就是第一个虚函数的函数地址,
//这里将其转换为函数类型
Fun pfun = (Fun)(ptbl[pos]); //调用这个函数
pfun();
调用的结果是:
B info : , test
说明调用了 B 类的虚函数,内存布局如下:
这样,我们使用非常规手段就可以调用一个类的虚函数了。
同步发表:http://www.fengbohello.top/book/b/1275
《深度探索C++对象模型》调用虚函数的更多相关文章
- [读书系列] 深度探索C++对象模型 初读
2012年底-2014年初这段时间主要用C++做手游开发,时隔3年,重新拿起<深度探索C++对象模型>这本书,感觉生疏了很多,如果按前阵子的生疏度来说,现在不借助Visual Studio ...
- 深度探索C++对象模型
深度探索C++对象模型 什么是C++对象模型: 语言中直接支持面向对象程序设计的部分. 对于各个支持的底层实现机制. 抽象性与实际性之间找出平衡点, 需要知识, 经验以及许多思考. 导读 这本书是C+ ...
- c++学习书籍推荐《深度探索C++对象模型》下载
百度云及其他网盘下载地址:点我 百度云及其他网盘下载地址:点我 编辑推荐 如果你是一位C++程序员,渴望对于底层知识获得一个完整的了解,那么这本<深度探索C++对象模型>正适合你 作者简介 ...
- 《深度探索C++对象模型》读书笔记(一)
前言 今年中下旬就要找工作了,我计划从现在就开始准备一些面试中会问到的基础知识,包括C++.操作系统.计算机网络.算法和数据结构等.C++就先从这本<深度探索C++对象模型>开始.不同于& ...
- 读书笔记《深度探索c++对象模型》 概述
<深度探索c++对象模型>这本书是我工作一段时间后想更深入了解C++的底层实现知识,如内存布局.模型.内存大小.继承.虚函数表等而阅读的:此外在很多面试或者工作中,对底层的知识的足够了解也 ...
- 拾遗与填坑《深度探索C++对象模型》3.3节
<深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...
- 拾遗与填坑《深度探索C++对象模型》3.2节
<深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...
- 【C++】深度探索C++对象模型读书笔记--Data语意学(The Semantics of data)
1. 一个空类的大小是1 byte.这是为了让这一类的两个对象得以在内存中配置独一无二的地址. 2. Nonstatic data member 放置的是“个别的class object”感兴趣的数据 ...
- C++中构造函数能调用虚函数吗?(答案是语法可以,输出错误),但Java里居然可以
环境:XPSP3 VS2005 今天黑总给应聘者出了一个在C++的构造函数中调用虚函数的问题,具体的题目要比标题复杂,大体情况可以看如下的代码: class Base { public: Base() ...
- EC笔记,第二部分:9.不在构造、析构函数中调用虚函数
9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #; } 上述程序会产生什么样的输出呢? 你一定会以为会输出: cls2 make cls2 delete ...
随机推荐
- Linux学习之RPM包管理-rpm命令管理(十六)
Linux学习之RPM包管理-rpm命令管理 目录 简介 RPM包依赖性 包全名与包名 rpm软件包安装 rpm软件包卸载 升级降级rpm软件包 rpm软件包的查询 rpm软件包校验 简介 RPM是R ...
- 大数据技术 - MapReduce的Shuffle及调优
本章内容我们学习一下 MapReduce 中的 Shuffle 过程,Shuffle 发生在 map 输出到 reduce 输入的过程,它的中文解释是 “洗牌”,顾名思义该过程涉及数据的重新分配,主要 ...
- asp.net结合html使用
在用asp.net开发系统时,用控件能更方便快捷,但是大家也知道用它的控件会导致不可控,特别是css,如何用前端定义的html+css+js来运用asp.net(c#)呢,下面写了一个小实例,实现页面 ...
- javascript的严格模式和正常模式
在js代码中加入"use strict";就相当于进入严格模式,严格模式改变了语法和运行时行为,将隐藏的问题转化为错误. js的严格模式有以下特点: 一.变量声明 全局变量必须显示 ...
- vue中的jsx
一.配置文件package.json { "name": "vuetest", "version": "1.0.0", ...
- csdn 站点使用
大学时使用csdn下载软件资源,最终csdn成为一个it中很重要站点,csdn的运营方式值得思考.
- RMQ问题 [luogu 3865]
原题地址 ST表模板题,尝试用单点修改线段树. 原本以为线段树会被卡掉,但是还是险过了.实践证明,快速读入很有用. #include<bits/stdc++.h> using namesp ...
- 前缀和的应用 CodeForces - 932B Recursive Queries
题目链接: https://vjudge.net/problem/1377985/origin 题目大意就是要你把一个数字拆开,然后相乘. 要求得数要小于9,否则递归下去. 这里用到一个递归函数: i ...
- 潭州课堂25班:Ph201805201 django 项目 第四十三课 后台 用户管理前后功能实现 (课堂笔记)
用户的展示,编辑,删除, 把用户显示出来,用户名,员工(是,否), 超级用户(是, 否) 活跃状态,(非活跃示为删除) 在前台要显示该用户所属的用户组,在前台代码中是调用类的属性,所以在 user 的 ...
- [LOJ6469]Magic
[LOJ6469]Magic 题目大意: 有\(n(n\le10^5)\)个物品,每个物品有一个权值\(w_i(w_i\le10^{18})\).求所有\(n\choose 2\)对物品\((i,j) ...