虚函数表的问题

article/2025/10/4 5:33:03

虚函数表:

多态是由虚函数实现的,而虚函数主要是通过虚函数表(V-Table)来实现的。

如果一个类中包含虚函数(virtual修饰的函数),那么这个类就会包含一张虚函数表,虚函数表存储的每一项是一个虚函数的地址。如下图:

这里写图片描述

这个类的每一个对象都会包含一个虚指针(虚指针存在于对象实例地址的最前面,保证虚函数表有最高的性能),这个虚指针指向虚函数表。

注:对象不包含虚函数表,只有虚指针,类才包含虚函数表,派生类会生成一个兼容基类的虚函数表。

· 原始基类的虚函数表:
  下图是原始基类的对象,可以看到虚指针在地址的最前面,指向基类的虚函数表(假设基类定义了3个虚函数)
这里写图片描述

· 单继承时的虚函数(无重写基类虚函数)
假设现在派生类继承基类,并且重新定义了3个虚函数(是派生类自己的虚函数),派生类会自己产生一个兼容基类虚函数表的属于自己的虚函数表。
这里写图片描述

Derive class 继承了 Base class 中的三个虚函数,准确的说,是该函数实体的地址被拷贝到 Derive类的虚函数表,派生类新增的虚函数置于虚函数表的后面,并按声明顺序存放。

· 单继承时的虚函数(重写基类虚函数)
现在派生类重写基类的x函数,可以看到这个派生类构建自己的虚函数表的时候,修改了base::x()这一项,指向了自己的虚函数。
这里写图片描述

· 多重继承时的虚函数(Derived ::public Base1,public Base2)
这个派生类多重继承了两个基类base1,base2,因此它有两个虚函数表。
这里写图片描述
  

  它的对象会有多个虚指针(据说和编译器相关),指向不同的虚函数表。

  多重继承时指针的调整:

Derive b;
Base1* ptr1 = &b;   // 指向 b 的初始地址
Base2* ptr2 = &b;   // 指向 b 的第二个子对象

因为 Base1 是第一个基类,所以 ptr1 指向的是 Derive 对象的起始地址,不需要调整指针(偏移)。

因为 Base2 是第二个基类,所以必须对指针进行调整,即加上一个 offset,让 ptr2 指向 Base2 子对象。

当然,上述过程是由编译器完成的。

Base1* b1 = (Base1*)ptr2;
b1->y();                   // 输出 Base2::y()
Base2* b2 = (Base2*)ptr1;
b2->y();                   // 输出 Base1::y()

其实,通过某个类型的指针访问某个成员时,编译器只是根据类型的定义查找这个成员所在偏移量,用这个偏移量获取成员。
由于 ptr2 本来就指向 Base2 子对象的起始地址,所以b1->y()调用到的是Base2::y(),而 ptr1 本来就指向 Base1 子对象的起始地址(即 Derive对象的起始地址),所以b2->y()调用到的是Base1::y()。


http://chatgpt.dhexx.cn/article/eKwxqgCi.shtml

相关文章

虚函数表详解及其应用场景

目录 概述1. 虚函数表概述2. 虚函数表的实现原理2.1. 虚函数的声明和定义2.2. 虚函数表的创建和初始化2.3. 虚函数调用的过程 3. 虚函数表的应用场景3.1. 多态性3.2. 基类指针和引用的使用3.3. 动态绑定3.4. 接口定义 结论 概述 在面向对象编程中,虚函数表&#xf…

C++ 面试必问:深入理解虚函数表

点击蓝字 关注我们 深入理解C 虚函数表 C中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。 Derive d; Base1 *b1 &d; Base2 *b2 &d; Base3 *b3 …

C++ 虚函数表

C类在内存中的存储方式 C 内存分为 5 个区域: 堆 heap :由 new 分配的内存块,其释放编译器不去管,由程序员自己控制。如果程序员没有释放掉,在程序结束时系统会自动回收。涉及的问题:“缓冲区溢出”、“内…

ThinkPHP3.2.2获取数据列getField()优化

getField()是一个常用方法,我习惯用来获取带key的数组,方便数据整合。 使用第1个参数,传入一个字段名,获取某一个数据值,返回满足条件的数据表中的该字段的第一行的值: $id M("User")->getFi…

java class getfield_java.lang.Class.getField()方法实例

全屏 java.lang.Class.getField() 返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段。 name参数是一个字符串,指定所需字段的简单名称。 声明 以下是java.lang.Class.getField()方法的声明public Field getField(String name) th…

java getfield_Java 反射:通过 getField() 设置公共全局变量

Java 通过 getField() 操作公共全局变量 以前写 JavaWeb 项目启动初始化系统配置全局变量的代码,都是 variable Properties.getProperty(name) 这样一行一行代码的设置,变量少还好说,变量一多真的很磨叽。所以一直想通过 循环 简化代码&…

getField和getDeclaredField的区别

这两个方法都是用于获取字段 1.getField 只能获取public的,包括从父类继承来的字段。 2.getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不…

vscode插件开发总结

一、关于vscode插件 相信大家对vscode应该都不陌生,VSCode是微软出的一款轻量级代码编辑器,免费而且功能强大,以功能强大、提示友好、不错的性能和颜值俘获了大量开发者的青睐,对JavaScript和NodeJS的支持非常好,自带…

2021-前端-VsCode插件

此乃吾习前端,VsCode之插件,个人所装,喜着自拿,不足之处还望海涵,多加批评。 1.Auto Close Tag——自动闭合尾部的标签 2.Atuo Rename Tag——修改 html 标签 自动帮你完成头部和尾部闭合标签的同步修改 3.Bracket…

关于VSCode插件的安装位置

VSCode的插件地址修改_上善若泪-CSDN博客_vscode插件位置文章目录1 data文件夹2 使用--extensions-dir命令3 使用mklink命令vscode编辑器强大的地方是可以使用各种各样的插件,但是插件默认的地方是在:C盘,让一些强迫症可能会受不了,非要迁移到…

vscode 插件-常用插件

VSCode常用插件(安装步骤同汉化) 1、*Auto Close Tag (自动闭合HTML/XML标签) 2、*Auto Rename Tag (自动帮你完成尾部闭合标签的同步修改,不过有些bug) 3、*Prettier(Prettier 是目前 Web 开发中最受欢迎的代码格式化程序) 安装Prettier -Code formatter这个插件…

Vscode 插件包下载并离线安装

打开VSCode插件官网 官网链接是https://marketplace.visualstudio.com/vscode 搜索Go 在输入框中输入go,搜索,结果如下: 点击Download Extension下载 注意:有时候找不到Download Extension,可能是网速加载慢&…

VsCode插件安装及推荐

1、快捷键Ctrl P,打开插件,输入 ext install (我习惯的输入方式); 2、或者点击图片中的圈红的按钮,也可以进入插件安装商城; 3、下面开始说下我目前安装的插件(我目前是vue开发&…

VScode安装离线插件

1. 下载及安装 首先在VScode官方插件库下载自己所需要的插件:https://marketplace.visualstudio.com/vscode 下载成功之后是以**.vsix**结尾的文件 然后再VScode软件中进行导入刚下载的文件 如果提示蓝色信息则为安装成功,红色则为失败 2. 版本不兼容报…

VSCode前端必备插件

跨平台的文本编辑器。由于其卓越的性能和丰富的功能,它很快就受到了大家的喜爱。 就像大多数 IDE 一样,VSCode 也有一个扩展和主题市场,包含了数以千计质量不同的插件。为了帮助大家挑选出值得下载的插件,我们针对性的收集了一些…

如何写一个vscode插件

1.运行yo code创建项目 2.选择使用yarn或者npm 3.运行 官网这个例子需要我们 ctrl shirt p 调出输入框, 然后在里面输入hello w 就可以如图所示 activationEvents: 当什么情况下, 去激活这个插件 activationEvents.onCommand: 在某个命令下激活(之后会专门列出很多其他条件…

Python好用的VSCode插件

1. Better Comments 这是一个让你能更好地编写注释的工具,它能根据关键词用不同的颜色高亮代码片段。支持以下类型的高亮: 感叹号 “!” 代码警告。问号“?”代表存留疑问。TODO 代码未来将要进行的操作。param 参数 2. autoDocstring 能够自动生成函…

VScode插件(自用)

一、Material Icon Theme 图标插件 它采用了 Google Material Design 风格,文件图标以及文件夹图标覆盖非常的全面。 二、 颜色主题插件Themes(代码颜色)中的 Monokai Dimmed 三、css peek 使用此插件,你可以追踪至样式表中 CSS…

2022年好用的Vscode插件

Chinese(VSCode汉化插件) 第一款推荐的插件叫Chinese 是一款VSCode汉化插件 这样,VSCode就完成了汉化 Material Theme(主题插件) 第二款插件是一个好看的主题插件Material Theme 它包含了多套不同色彩风格的主题,以及好看的图标样式。 选择不同主题可以…

VSCode 插件

文章目录 VSCode 插件 VSCode 插件 图标插件作用Auto Import在j\ts文件中,直接使用外部依赖包的变量名,此时,会自动写入导入语句Bracket Pair Colorizer2VS Code 已经内置Chinese (Simplified) (简体中文)汉化Code Spell Checker适用于代码和…