探索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 ...
随机推荐
- 入参是小数的String,返回小数乘以100的String
String money = request.getParameter("orderAmt"); BigDecimal moneyDecimal = new BigDecimal( ...
- Swift学习——Swift基础具体解释(一)
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhenyu5211314/article/details/34807025 注:由于基础部分在Swi ...
- Spark ML Pipeline简介
Spark ML Pipeline基于DataFrame构建了一套High-level API,我们可以使用MLPipeline构建机器学习应用,它能够将一个机器学习应用的多个处理过程组织起来,通过在 ...
- PHPcms v9 get标签sql 语句limit无效问题的解决方法
get标签非常好用,自定义模型后get几乎变成万能的了.但是PHPCMS升级到V9后,把2008的很多功能都去掉了,比如get标签中,在后面自动添加了一个LIMIT 0,20,这样你即使写了num=' ...
- Hadoop2.7.3+spark2.1.0+hbase0.98分布式集群部署
运行环境配置(10.79.115.111-114) 1.关闭防火墙与selinux 关闭防火墙: CentOS 7.x默认使用的是firewall作为防火墙. systemctl stop firew ...
- MongoDB的固定集合
一.MongoDB固定集合概念 固定集合指的是事先创建,并且大小固定的集合.即假设一个集合设置了固定大小为100,再添加一条文档的时候,会把最前面的文档剔除,永远只保留100条数据. 固定集合特性:固 ...
- MFC中对基于ODBC对数据ACCESS数据库的增删改查。
在MFC中可以使用很多方法对数据库进行操作. 什么ODBC 什么ADO之类的,这里要介绍使用的ODBC这种方法,通过本文的阅读可以达初步掌握在MFC里面通过ODBC访问ACCESS数据库. 涉及到的 ...
- debian7更换gcc版本的二种方法分享
debian7更换gcc版本的二种方法分享 最近在编译qt,之前用的是debian6,gcc版本是gcc-4.4,当使用debian7时,编译遇到了很多跟debian6不一样的问题,debian7 ...
- Linux系统——文件和目录权限
文件及目录权限(七进制表示) r 读权限(4),允许查看文件内容 w 写权限(2),允许修改文件内容 x 可执行权限(1),允许运行程序 - 无权限(0) 属主:拥有该文件的用户账号 属组:拥有该 ...
- Oracle数据库面试题(转)
1. Oracle跟SQL Server 2005的区别? 宏观上: 1). 最大的区别在于平台,oracle可以运行在不同的平台上,sql server只能运行在windows平台上,由于windo ...