C++ vtordisp的应用场景

文章目录

      • 问题代码
      • 1. 基本概念回顾
      • 2. 应用场景
        • 虚继承与虚函数并存的类层次结构
      • 3. 编译器相关考虑

问题代码

#include <iostream>
using namespace std;class base
{
public:base() {}virtual void show() { cout << "base:: show"<<endl; }
private:int ma;
};class derive:virtual public base
{
public:derive() {}virtual void show() { cout << "derive:: show"; }
private:int mb;
};int main()
{cout << sizeof(derive) << endl;
}

以上代码类大小常规来说应该是如下,占16个字节大小,但是为何是20呢
预期结构

class derive    size(16):+---0      | {vbptr}4      | mb+---+--- (virtual base base)8      | {vfptr}
12      | ma+---

实际结构,占大小20个字节

class derive    size(20):+---0      | {vbptr}4      | mb+---
8       | (vtordisp for vbase base)+--- (virtual base base)
12      | {vfptr}
16      | ma+---derive::$vbtable@:0      | 01      | 12 (derived(derive+0)base)derive::$vftable@:| -120      | &(vtordisp) derive::showderive::show this adjustor: 12
vbi:       class  offset o.vbptr  o.vbte fVtorDispbase      12       0       4 1

在这里插入图片描述
经过验证 必须满足以下两个条件

  1. 派生类重写了虚基类的虚函数。
  2. 派生类定义了构造函数或者析构函数。
    才会产生vtordisp.
    这就牵扯到vtordisp了,介绍如下

1. 基本概念回顾

在 C++ 中,当涉及虚继承时,为了确保在派生类对象中能正确定位虚基类的子对象(包含虚基类的数据成员、虚函数等内容),编译器会在派生类对象的内存布局中安排虚基类表指针等相关结构来记录偏移量信息,以实现准确访问虚基类部分。同时,对于有虚函数的类,会存在虚函数表(VTable)来支持多态调用。

vtordisp 主要用于处理虚继承和虚函数结合场景下,构造函数和析构函数中对虚基类指针调整的一种机制,它本质上是编译器为了正确处理对象的初始化和析构顺序、保证虚基类相关操作的正确性而引入的一个额外的字节(在 32 位系统下通常是 4 字节,64 位系统下通常是 8 字节)来存储偏移量相关信息。

2. 应用场景

虚继承与虚函数并存的类层次结构
  • 场景描述:当类层次结构中既有虚继承又有类自身包含虚函数的情况时,在派生类的构造函数和析构函数中,需要准确地处理与虚基类相关的初始化和清理工作,同时还要考虑虚函数机制带来的多态性影响。

3. 编译器相关考虑

  • 不同的编译器对于 vtordisp 的处理可能会有一些差异,有些编译器可能会根据具体的类层次结构复杂度、是否确实存在需要调整虚基类指针偏移量的情况等来决定是否启用 vtordisp 机制以及如何分配相应的字节来存储相关信息。比如在 Visual C++ 编译器中,对于符合特定条件的虚继承和虚函数结合的场景,会自动插入 vtordisp 相关代码来处理对象布局和操作顺序问题,而在 GCC 等其他编译器中,也有其对应的实现方式和判断标准来确保在类似场景下的代码正确性。

如果不想要vtordisp 可以加 #pragma vtordisp(off) 进行关闭。

vtordisp是Visual C++编译器的一个特性,主要用于解决在类继承中,虚函数的调用与对象布局的问题。当你在类中使用了虚函数,并且该类被继承,且继承类覆盖了基类的虚函数时,可能会出现所谓的"跳跃问题"(slicing problem)。

"跳跃问题"是指当你有一个基类的指针指向派生类对象,并且调用了虚拟函数,预期是派生类的函数被调用,但实际上可能会调用基类的函数。这是因为编译器为了能够快速地调用虚拟函数,直接使用了指针的偏移量来计算虚拟函数的地址,而不是检查实际对象的类型。

为了解决这个问题,当你在类中有一个或多个虚拟函数,并且类被继承,且派生类覆盖了基类的虚函数时,编译器可能会为类添加一个额外的隐藏成员,称为vtordisp字段。vtordisp字段的作用是在构造函数和析构函数执行过程中,记录对象的实际类型信息,以便正确地调用虚拟函数。具体由编译器进行管理。

在网上搜集资料并未搞清楚其底层原理,请知道的大佬不吝赐教。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/892578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git:merge合并、冲突解决、强行回退的终极解决方案

首先还是得避免冲突的发生&#xff0c;无法避免时再去解决冲突&#xff0c;避免冲突方法&#xff1a; 时常做pull、fatch操作&#xff0c;不要让自己本地仓库落后太多版本&#xff1b;在分支操作&#xff0c;如切换分支、合并分支、拉取分支前&#xff0c;及时清理Change&#…

2025网络架构

一、园区网络概述。 园区网络典型层次和区域&#xff1a; 核心层&#xff1a;是园区网骨干&#xff0c;是园区数据交换的核心&#xff0c;联接园区网的各个组成部分&#xff0c;如数据中心、管理中心、园区出口等。汇聚层&#xff1a;处于园区网的中间层次&#xff0c;完成数据…

Vue.config.productionTip = false 不起作用的问题及解决

文章目录 一、问题描述二、解决方法 一、问题描述 当我们在代码页面上引入Vue.js(开发版本)时&#xff0c;运行代码会出现以下提示&#xff0c;这句话的意思是&#xff1a;您正在开发模式下运行Vue&#xff0c;在进行生产部署时&#xff0c;请确保打开生产模式 You are runni…

【经管数据】ZF数字采购采购明细数据(2015.3-2024.3)

一、数据来源&#xff1a; 原始数据来源为ZF采购网。数据涵盖了自2015年3月至2024年3月的ZF数字采购合同明细&#xff0c;反映了数字化转型在政府采购中的应用情况。 二、参考文献&#xff1a; [1] 申志轩, 祝树金, 文茜, 等. ZF数字采购与企业数字化转型[J]. 数量经济技术经济…

啥!GitHub Copilot也免费使用了

文章目录 前言免费版直接修复代码多文件上下文Agent模式总结 前言 最近&#xff0c;GitHub 给开发者们带来了一个好消息&#xff1a;他们的 AI 编程助手 GitHub Copilot 现在可以免费使用了&#xff01;以前&#xff0c;每个月要花 10 美元才能享受的服务&#xff0c;现在对所…

013:深度学习之神经网络

本文为合集收录&#xff0c;欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请参考这里。 深度学习是机器学习中重要的一个学科分支&#xff0c;它的特点就在于需要构建多层且“深度”的神经网络。 人们在探索人工智能初期&#xff0c;就曾设想构建一个用数学方式…

【NLP】语言模型的发展历程 (1)

语言模型的发展历程系列博客主要包含以下文章&#xff1a; 【NLP】语言模型的发展历程 (1)【NLP】大语言模型的发展历程 (2) 本篇博客是该系列的第一篇&#xff0c;主要讲讲 语言模型&#xff08;LM&#xff0c;Language Model&#xff09; 的发展历程。 文章目录 一、统计语…

JNI使用类签名及字段签名获取字段值

1.获取逻辑: 2.获取逻辑实现代码: extern "C" JNIEXPORT void JNICALL Java_com_example_jnibasetypedemo_MainActivity_getAnimalsNameFromJNI(JNIEnv *env, jobject thiz,jobjectArray animals) {jobject animalObj;int len env->GetArrayLength(animals);//获…

Vue 封装公告滚动

文章目录 需求分析1. 创建公告组件Notice.vue2. 注册全局组件3. 使用 需求 系统中需要有一个公告展示&#xff0c;且这个公告位于页面上方&#xff0c;每个页面都要看到 分析 1. 创建公告组件Notice.vue 第一种 在你的项目的合适组件目录下&#xff08;比如components目录&a…

Win10微调大语言模型ChatGLM2-6B

在《Win10本地部署大语言模型ChatGLM2-6B-CSDN博客》基础上进行&#xff0c;官方文档在这里&#xff0c;参考了这篇文章 首先确保ChatGLM2-6B下的有ptuning AdvertiseGen下载地址1&#xff0c;地址2&#xff0c;文件中数据留几行 模型文件下载地址 &#xff08;注意&#xff1…

HTTP-响应协议

HTTP的响应过程&#xff1f; 浏览器请求数据--》web服务器过程&#xff1a;请求过程 web服务器将响应数据-》到浏览器&#xff1a;响应过程 响应数据有哪些内容&#xff1f; 1.和请求数据类似。 2. 响应体中存储着web服务器返回给浏览器的响应数据。并且注意响应头和响应体之间…

爬虫基础之爬取歌曲宝歌曲批量下载

声明&#xff1a;本案列仅供学习交流使用 任何用于非法用途均与本作者无关 需求分析: 网站:邓紫棋-mp3在线免费下载-歌曲宝-找歌就用歌曲宝-MP3音乐高品质在线免费下载 (gequbao.com) 爬取 歌曲名 歌曲 实现歌手名称下载所有歌曲 本案列所使用的模块 requests (发送…

C++ 鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

2025年中科院分区大类划分公布!新增8155本

2025年中科院分区表变更情况 扩大收录范围 2025年的期刊分区表在原有的自然科学&#xff08;SCIE&#xff09;、社会科学&#xff08;SSCI&#xff09;和人文科学&#xff08;AHCI&#xff09;的基础上&#xff0c;增加了ESCI期刊的收录&#xff0c;并根据这些期刊的数据进行…

【前端动效】HTML + CSS 实现打字机效果

目录 1. 效果展示 2. 思路分析 2.1 难点 2.2 实现思路 3. 代码实现 3.1 html部分 3.2 css部分 3.3 完整代码 4. 总结 1. 效果展示 如图所示&#xff0c;这次带来的是一个有趣的“擦除”效果&#xff0c;也可以叫做打字机效果&#xff0c;其中一段文本从左到右逐渐从…

提升租赁效率的租赁小程序全解析

内容概要 在如今快节奏的生活中&#xff0c;租赁小程序俨然成为了提升租赁效率的一把利器。无论是个人还是企业&#xff0c;都会因其便捷的功能而受益。简单来说&#xff0c;租赁小程序能让繁琐的租赁流程变得轻松、高效。在这里&#xff0c;我们将带您畅游租赁小程序的海洋&a…

Docker--Docker Compose(容器编排)

什么是 Docker Compose Docker Compose是Docker官方的开源项目&#xff0c;是一个用于定义和运行多容器Docker应用程序的工具。 服务&#xff08;Service&#xff09;&#xff1a;在Docker Compose中&#xff0c;一个服务实际上可以包括若干运行相同镜像的容器实例&#xff0…

搭建docker私有化仓库Harbor

Docker私有仓库概述 Docker私有仓库介绍 Docker私有仓库是个人、组织或企业内部用于存储和管理Docker镜像的存储库。Docker默认会有一个公共的仓库Docker Hub,而与Docker Hub不同,私有仓库是受限访问的,只有授权用户才能够上传、下载和管理其中的镜像。这种私有仓库可以部…

本地视频进度加入笔记+根据进度快速锁定视频位置

本地视频进度记录快速回溯 引言 在学习的过程中, 如果我们想快速记录当前看视频的位置, 后续回溯查找就会非常方便了。 实现效果 进度记录 通过按下快捷键ctrlaltu&#xff0c; 快速记录当前视频的进度信息,然后复制到typora软件内 快速回溯 在typora软件内, 选中视频索引…

网络传输层TCP协议

传输层TCP协议 1. TCP协议介绍 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一个要对数据的传输进行详细控制的传输层协议。 TCP 与 UDP 的不同&#xff0c;在于TCP是有连接、可靠、面向字节流的。具体来说&#xff0c;TCP设置了一大…