C++虚表

对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。

class Base {

public:

virtual void f() { cout << "Base::A" << endl; }

virtual void g() { cout << "Base::B" << endl; }

virtual void h() { cout << "Base::C" << endl; }

};

typedef void(*Fun)(void);

Base D;

cout << "虚函数表地址:" << (int*)(&D) << endl;

cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&D) << endl;

     (Fun)*((int*)*(int*)(&D)+0);  // Base::A()

(Fun)*((int*)*(int*)(&D)+1);  // Base::B()

(Fun)*((int*)*(int*)(&D)+2);  // Base::C()

值得注意的是当中的int和整形并没有任何的关系,int只是它正好也是4个字节这样可以对虚表的地址进行操作,从而读出虚表的内容

时间: 2024-10-05 18:39:45

C++虚表的相关文章

C++再次理解虚表

#include <iostream> using namespace std; class Base { public: virtual void fun1() { cout << "Base::fun1()" << endl; } virtual void fun2() { cout << "Base::fun2()" << endl; } }; class Son : public Base { pu

类虚函数表原理实现分析(当我们将虚表地址[n]中的函数替换,那么虚函数的实现就由我们来控制了)

原理分析 当调用一个虚函数时, 编译器生成的代码会调用 虚表地址[0](param1, param2)这样的函数. 已经不是在调用函数名了. 当我们将虚表地址[n]中的函数实现改为另外的函数, 虚函数的实现就由我们来控制了. 实验 根据虚表原理, 实验一下修改自己程序的虚函数表项地址. 使编译器生成的代码执行一个虚函数A时, 执行的是我们自己定义的非虚函数B. 知识点 * 使用union赋值, 绕过编译器函数与变量强转赋值的限制 * 类成员函数指针的执行 * 修改和恢复自己的代码段属性 * 虚函

虚表(Vtables)

虚表是一组虚函数指针. 在COM中,接口的结构就像一个虚表.正如先前所提到的,这是虚函数表的缩写,并且它只是一组公开接口功能的一组指针.虚表展示COM客户端能访问他们的标准方法.虚表不变的布局定促使COM定义了一个二进制标准.只要组件支持这种二进制虚表标准,它就能用其他支持同样标准的组件进行操作.必要的虚表.使用一个COM虚表等同于使用C++调用一个虚函数.如此,C++就与COM完全兼容.

【转载】C/C++杂记:深入虚表结构

原文:C/C++杂记:深入虚表结构 1. 虚表与“虚函数表” 在“C/C++杂记:虚函数的实现的基本原理”一文中曾提到“虚函数表”的概念,只是为了便于理解,事实是:虚函数表并不真的独立存在,它只是虚表(virtual table)中的一部分内容.例: 从图中可已看出,虚表除了包含虚函数指针,还包含其它一些信息(如:RTTI信息.偏移值等). 顺便介绍一下gcc的-fdump-class-hierarchy选项,它可以用于输出C++程序的虚表结构(在当前目录下生成一个.class文件),例: 2.

虚函数——虚表总结

非虚拟继承 [带虚函数的类] class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"<<endl; } virtual void FunTest2() { cout<<"Base::FunTest2()"<<endl; } int _data1; }; int main() { Base b; b._data1 = 0x01; re

C++基础之多态虚表中我一直的误区!

之前我的认识: 子类继承拥有虚函数的父类,并且没有重写虚函数 ----子类的虚表地址与父类虚表地址相同 代码: _vfptr:虚表的地址 由此可见,虚表地址pE的是0x01162100,pF的是0x01162108

C++里面virtual函数及虚表大小

实验了下面的函数: #include <vector> #include <iostream> using namespace std; class A { public: virtual int a(){} virtual int b(){} virtual int c(){} virtual int d(){} virtual int e(){} virtual int f(){} virtual int g(){} int t; }; int main() { A a; co

揭开C++类中虚表的“神秘面纱”

C++类中的虚表结构是C++对象模型中一个重要的知识点,这里咱们就来深入分析下虚表的在内存中的结构. C++一个类中有虚函数的话就会有一个虚表指针,其指向对应的虚表,一般一个类只会有一个虚表,每个虚表有多个”插槽”,每个插槽存放一个虚函数的地址.插槽中的内容可以被覆盖,子类如果重写了父类中的虚函数,则插槽中对应位置的数据被覆盖.虚表存放的是虚函数地址,不管该虚函数是public还是private的.光文字说明不太形象,下面上一张虚表结构的示例图: 从图中看出,虚表指针确实是指向虚表结构的,这个虚

C++中new和delete的背后( call edx 调用虚表内的第二个函数(析构函数))

关于 C++中new背后的行为, 以前已经写过一篇了 理解C++中new背后的行为, 但是里面也只是泛泛而谈,没有真凭实据, 下面我们从汇编的角度看C++编译器究竟在背后干了什么? 我们的代码很简单, 如下: #include <iostream> class A { public: virtual void print() { std::cout << 10; } virtual ~A() { std::cout << "~A()"; } }; c

在类有成员变量的场景下, 按照虚表原理, 模拟虚函数实现

前言 当类没有成员变量的情况下,   类首地址有4个字节的空间, 这里可以放我们模拟出来的虚表入口地址. 当类有成员变量的情况下, 类首地址就是成员变量,  所以, 为了模拟虚表实现, 需要在成员变量前, 再定义一个int型变量, 用来存放模拟的虚表入口地址. 现在还得不到虚析构函数的地址, 暂时按照非虚析构函数进行模拟. 这个实验是在C++中模拟的. 模拟虚函数实现的用途 在非OOP语言(C语言)中, 模拟类的实现, 可以实现虚函数的效果. 效果 工程下载点 编译环境: vc6sp6 + wi