探索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++虚函数的更多相关文章

  1. 探索C++虚函数在g++中的实现

    本文是我在追查一个诡异core问题的过程中收获的一点心得,把公司项目相关的背景和特定条件去掉后,仅取其中通用的C++虚函数实现部分知识记录于此. 在开始之前,原谅我先借用一张图黑一下C++: “无敌” ...

  2. 《深度探索C++对象模型》调用虚函数

    如果一个类有虚函数,那么这个类的虚函数会被放在一个虚函数表里面, 使用这个类声明的对象中,会有一个指向虚函数表的指针,当使用指向 这个对象的指针或者这个对象的引用调用一个虚函数的时候,就会从虚函数表中 ...

  3. 【深度探索c++对象模型】Function语义学之虚函数

    虚函数的一般实现模型:每一个class有一个virtual table,内含该class中的virtual function的地址,然后每个object有一个vptr,指向virtual table. ...

  4. 匹夫细说C#:从园友留言到动手实现C#虚函数机制

    前言 上一篇文章匹夫通过CIL代码简析了一下C#函数调用的话题.虽然点击进来的童鞋并不如匹夫预料的那么多,但也还是有一些挺有质量的来自园友的回复.这不,就有一个园友提出了这样一个代码,这段代码如果被编 ...

  5. C++虚函数浅探

    C++中和虚函数(Virtual Function)密切相关的概念是"动态绑定"(Dynamic Binding),与之相对的概念是"静态绑定"(Static ...

  6. C++中为什么要用虚函数、指针或引用才能实现多态?

    原文链接:http://blog.csdn.net/zoopang/article/details/14071779 学过C++的都知道,要实现C++的多态性必须要用到虚函数,并且还要使用引用或者指针 ...

  7. C++虚函数及虚函数表解析

    一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Functio ...

  8. 【转】C++虚函数解析

    本文转自陈皓大叔(左耳朵耗子)的博客www.coolshell.com. 文章是很久之前所写,去年还在写C++时有幸拜读,现在想起来还是相当有价值一转的,如果有一定C++基础(特别是读过<深度探 ...

  9. [GeekBand] C++继承关系下虚函数内存分布

    本文参考文献:GeekBand课堂内容,授课老师:侯捷 :深度探索C++对象模型(侯捷译) :网络资料,如:http://blog.csdn.net/sanfengshou/article/detai ...

随机推荐

  1. MySQL与Btree

    Btree,B+tree,B*tree 前言: 由于在查找中用二分法在查找一些边缘数据时就会产生数据查找不公平,二叉树也存在类似问题:所以就有了B-tree. B+树索引是B+树在数据库中的一种实现, ...

  2. GC的性能指标和内存容量配置原则

    一.GC性能指标吞吐量:应用花在非GC上的时间百分比GC负荷:与吞吐量相反,指应用花在GC上的时间百分比暂停时间:应用花在GC stop-the-world的时间GC频率反应速度:从一个对象变成垃圾到 ...

  3. Oracle 性能调优 SQL_TRACE

    思维导图 Oracle优化10-SQL_TRACE解读 Oracle优化11-10046事件 概述 当我们想了解一条SQL或者是PL/SQL包的运行情况时,特别是当他们的性能非常差时,比如有的时候看起 ...

  4. Oracle 性能调优 10053事件

    思维导图 10053事件概述 我们在查看一条SQL语句的执行计划时,只看到了CBO最终告诉我们的执行计划结果,但是我们并不知道CBO为何要这样做. 特别是当执行计划明显失真时,我们特别想搞清楚为什么C ...

  5. mysql数据库从删库到跑路之mysql数据类型

    一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考: http://www.runoob.com/mysql/mysql-data ...

  6. mysql5.7 linux安装参考

    安装参考: https://www.cnblogs.com/ianduin/p/7679239.html http://blog.csdn.net/wb96a1007/article/details/ ...

  7. 防止 IOS 和 安卓 自动锁屏

    Ios代码 在文件AppController中的 didFinishLaunchingWithOptions函数中加一行代码即可: [[UIApplication sharedApplication] ...

  8. Spark --【宽依赖和窄依赖】

    前言 Spark中RDD的高效与DAG图有着莫大的关系,在DAG调度中需要对计算过程划分stage,暴力的理解就是stage的划分是按照有没有涉及到shuffle来划分的,没涉及的shuffle的都划 ...

  9. 使用Spring Session和Redis解决分布式Session跨域共享问题

    http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题

  10. 【Linux学习】2.Linux常见命令行

    记录学习Linux 系统的相关知识点,欢迎大家拍砖交流,一起成长:QQ:2712192471 作者背景:前端开发工程师 | Python | web安全爱好者   Linux命令行: 系统关机重启 s ...