虚表的形成

一切结论都必须以事实为依据,这样才能形成长久记忆!

虚表的形成过程:

①对于非继承类而言:编译器会根据类中是否有虚函数产生虚表,如果有虚函数,则会形成虚表,虚表中会按照成员函数声明顺序存放函数的地址,从而形成存放函数入口地址的函数指针数组,最后把数组地址存放在类的开始的位置,只一个指针的大小。

②对于继承类而言:对于单继承,如果父类中有虚函数表,则编译器编译时,会把父类的虚表赋值一份,并把其地址放在类的开始,只占一个指针大小的空间;对于多继承,编译器会把多个父类的虚表地址按照继承顺序依次从类的开始位置存放其虚表指针。

③对于继承时,如果其重写其父类的虚函数(注意重写与重载的区别),编译器会把新的函数的地址更新到原来虚函数对应的位置,如果该类新增虚函数是,编译器会默认把新的虚函数的地址存放第一个虚表中,追加在其后。

④虚函数就是指成员函数前加virtual 关键字的函数,但构造函数和友元函数(不是类成员函数)不会是虚函数,其他成员函数都可以使用virtual 修饰,当然纯虚函数也是虚函数。

⑤补充:在c++中纯虚函数与纯面向对象的语言,如java、C#,中的接口在功能上是一致的,都是起到接口规范的作用,知识在C++中纯虚函数在类中定义,所以导致在C++中,继承可以是多继承方式,而在纯面向对象中,只能是单继承。

对于以上的验证,大家可以参考http://blog.csdn.net/haoel/article/details/1948051

时间: 2024-11-08 07:41:23

虚表的形成的相关文章

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