探索C++虚函数
探索C++虚函数
1 测试环境
各个编译器对虚函数的实现有各自区别,但原理大致相同。本文基于VS2008探索虚函数
2 测试代码
#pragma once
#include <iostream>
using namespace std;
class C1
{
public:
C1()
{
mem1 = ;
mem2 = ;
}
virtual void f1()
{
cout << "this is C1 f1" << endl;
}
virtual void f2()
{
cout << "this is C1 f2" << endl;
}
virtual ~C1()
{
cout << "this is C1 deconstruction" << endl;
}
int mem1;
int mem2;
}; typedef void (*Fun)(void); //调用虚函数
template<class F>
void CallVirtualFun(const int* p_virTableAddrPtr, const int index)
{
int funAddr = ; //定义函数地址数值,用int取函数地址
int* p_funAddr = NULL; //真实虚函数地址
F fun = NULL; //函数指针 memcpy(&funAddr ,p_virTableAddrPtr + index, ); //从虚函数表中取函数地址,结果保存在funAddr
p_funAddr = (int*)funAddr; //将函数地址数值转换为函数地址
fun = (F)p_funAddr; //转函数指针
fun(); //调用函数
} void VirtualFunByOffset()
{
C1 mC1;
//取出类地址
int* p_classAddr = (int*)(&mC1);
//取出虚表的地址,类的前4个字节是虚表指针,首先取出虚表地址
int virTableAddrInt = *p_classAddr;
//根据虚表的地址访问虚表,虚表每一项都是函数指针,占有4个字节
int* p_virTableAddrPtr = (int*)virTableAddrInt; //将虚函数地址转换为函数指针
CallVirtualFun<Fun>(p_virTableAddrPtr, ); //调用虚函数表的第一个虚函数
CallVirtualFun<Fun>(p_virTableAddrPtr, ); //调用虚函数表的第二个虚函数
};
3 类对象
3.1 虚函数表总是在类对象的起始位置

3.2 虚函数表中函数位置与声明顺序相关
声明虚虚构,看出虚析构函数在虚函数表中第一个位置

将虚析构挪到末尾处声明,看出虚析构在虚函数表末尾位置

3.3 类对象模型
以C1为例,构建对象模型,如下图所示:

- 类对象的最前面为指向虚表的指针(4个字节)
- 虚表的每一项对应类声明的虚函数指针(4个字节),因此,获取虚表的起始地址后,可以根据偏移获取到各个虚函数地址
- 虚函数的指针指向虚函数,只要知道虚函数的格式(声明),就可以调用对应的虚函数
4 代码调试访问虚表
本册测试结构为
首先创建一个类对象,通过类起始地址获取得到类的前4个字节,即虚表地址。

拿到虚表地址后,查看虚表。函数指针每4个字节为1个单位,下面的虚表地址下共有3个虚函数,虚表以0结束。

取得虚表的第一个函数,这里是C1::f1,地址是00 0a 10 c3,访问该地址。并将该地址转换为函数指针:

调用后进入函数体

探索C++虚函数的更多相关文章
- 探索C++虚函数在g++中的实现
本文是我在追查一个诡异core问题的过程中收获的一点心得,把公司项目相关的背景和特定条件去掉后,仅取其中通用的C++虚函数实现部分知识记录于此. 在开始之前,原谅我先借用一张图黑一下C++: “无敌” ...
- 《深度探索C++对象模型》调用虚函数
如果一个类有虚函数,那么这个类的虚函数会被放在一个虚函数表里面, 使用这个类声明的对象中,会有一个指向虚函数表的指针,当使用指向 这个对象的指针或者这个对象的引用调用一个虚函数的时候,就会从虚函数表中 ...
- 【深度探索c++对象模型】Function语义学之虚函数
虚函数的一般实现模型:每一个class有一个virtual table,内含该class中的virtual function的地址,然后每个object有一个vptr,指向virtual table. ...
- 匹夫细说C#:从园友留言到动手实现C#虚函数机制
前言 上一篇文章匹夫通过CIL代码简析了一下C#函数调用的话题.虽然点击进来的童鞋并不如匹夫预料的那么多,但也还是有一些挺有质量的来自园友的回复.这不,就有一个园友提出了这样一个代码,这段代码如果被编 ...
- C++虚函数浅探
C++中和虚函数(Virtual Function)密切相关的概念是"动态绑定"(Dynamic Binding),与之相对的概念是"静态绑定"(Static ...
- C++中为什么要用虚函数、指针或引用才能实现多态?
原文链接:http://blog.csdn.net/zoopang/article/details/14071779 学过C++的都知道,要实现C++的多态性必须要用到虚函数,并且还要使用引用或者指针 ...
- C++虚函数及虚函数表解析
一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Functio ...
- 【转】C++虚函数解析
本文转自陈皓大叔(左耳朵耗子)的博客www.coolshell.com. 文章是很久之前所写,去年还在写C++时有幸拜读,现在想起来还是相当有价值一转的,如果有一定C++基础(特别是读过<深度探 ...
- [GeekBand] C++继承关系下虚函数内存分布
本文参考文献:GeekBand课堂内容,授课老师:侯捷 :深度探索C++对象模型(侯捷译) :网络资料,如:http://blog.csdn.net/sanfengshou/article/detai ...
随机推荐
- 004-Maven的安装与配置
1.在Windows上安装Maven 1.1.检查jdk安装 命令行:echo %JAVA_HOME% java -version 1.2.下载Maven 地址:http://maven.apache ...
- Lepus_天兔的安装
一.安装平台 Centos 32位 二.依赖软件 依赖软件包:mysql.php.apache集成在xampp中,python,MySQLdb模块安装包在lepus安装包目录中 以下标红软件是必须安装 ...
- PAT 1145 Hashing - Average Search Time [hash][难]
1145 Hashing - Average Search Time (25 分) The task of this problem is simple: insert a sequence of d ...
- 机器学习第2周---炼数成金-----线性回归与Logistic
重点归纳 回归分析就是利用样本(已知数据),产生拟合方程,从而(对未知数据)迚行预测用途:预测,判别合理性例子:利用身高预测体重:利用广告费用预测商品销售额:等等.线性回归分析:一元线性:多元线性:广 ...
- [golang note] 内建类型
基础类型 √ golang内建基础类型有布尔类型.整数类型.浮点类型.复数类型.字符串类型.字符类型和错误类型. 复合类型 √ golang支持的复合类型有指针.数组.数组切片.字典.通道.结构体和接 ...
- 存储库之——MongoDB
阅读目录 一 简介 二 MongoDB基础知识 三 安装 四 基本数据类型 五 CRUD操作 六 可视化工具 七 pymongo 一 简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库1. ...
- CentOS 6.5上安装python2.7、pip以及Python命令行补全和yum冲突解决
目前CentOS6.5上自带的python版本为2.6,升级到python2.7会碰到很多问题.本文将介绍如何安装python2.7.pip以及python命令行补全. 一.如何安装python2.7 ...
- iOS 大批量弹幕小论(粒子弹幕)
一.现状 如今直播类.视频播放器等基本都有弹幕模式. 为了保持性能和内存可控,基本是在初始化的时候生成一个Pool(Pool的容量是设定好的), 也就是利用重用机制(可以想象一下UITableView ...
- dubbo-admin 监控中心 部署
dubbo-admin部署 下载: GitHub:https://github.com/search?q=dubbo-admin 百度网盘: 链接:https://pan.baidu.com/s/1v ...
- 20145328 《Java程序设计》第0周学习总结
20145328 <Java程序设计>第0周学习总结 阅读心得 从总体上来说,这几篇文章都是围绕着软件工程专业的一些现象来进行描述的,但深入了解之后就可以发现,无论是软件工程专业还是我们现 ...