探索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 ...
随机推荐
- mysql 约束条件 auto_increment 自动增长 创建表时设置自增字段
auto_increment mysql) )auto_increment; Query OK, rows affected (0.01 sec) mysql> show create tabl ...
- JavaScript Object.defineProperty()方法详解
Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 语法 Object.defineProperty(obj, prop ...
- HBase存储架构
以下的介绍是基于Apache Hbase 0.94版本: 从HBase的架构图上可以看出,HBase中的存储包括HMaster.HRegionServer.HRegion.Store.MemStore ...
- 《闪存问题之PROGRAM DISTURB》总结
来自 http://www.ssdfans.com/?p=1814 SSD之所以需要BCH或LDPC等ECC纠错算法,是因为闪存中的数据会在神不知鬼不觉的情况下发生比特翻转. 导致比特翻转的原因很多, ...
- 模块讲解----json与pickle模块的区别
1.在生产中,dumps和loads只进行一次,而且要用w把原来的数据冲掉,从而保证每次都是最新的. 2.虚拟机的快照,是每个快照都有一个文件,而不是全都不放在一起. 3.如果想生产好几个序列化,就生 ...
- IOS中程序如何进行推送消息(本地推送,远程推送)2(下)
内容中包含 base64string 图片造成字符过多,拒绝显示
- Delphi锁定鼠标 模拟左右键 静止一会自动隐藏鼠标
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- The Air Jordan 4 Oreo Remastered would be re-released in 2015
May be the Jordan 4 Oreo probably the most anticipated pair among the remastered Jordans for 2015? W ...
- POJ 3253 Fence Repair(简单哈弗曼树_水过)
题目大意:原题链接 锯木板,锯木板的长度就是花费.比如你要锯成长度为8 5 8的木板,最简单的方式是把21的木板割成13,8,花费21,再把13割成5,8,花费13,共计34,当然也可以先割成16,5 ...
- 『NiFi 学习之路』自定义 —— 组件的自定义及使用
一.概述 许多业务仅仅使用官方提供的组件不能够满足性能上的需求,往往要通过高度可定制的组件来完成特定的业务需求. 而 NiFi 提供了自定义组件的这种方式. 二.自定义 Processor 占坑待续 ...