反转生成的 vtable 函数顺序(具有相同名称的函数)

2023-12-11

如果使用 Visual Studio 2019,我使用两个具有相同名称但不同参数的虚拟方法来编译此 C++ 代码:

struct MyStruct
{
    virtual void foo(float) = 0;
    virtual void foo(int) = 0;
};

class MyClass : public MyStruct
{
public:
    void foo(float) {}
    void foo(int) {}
};

static MyClass c;

生成的类的 vtable 中方法的顺序是相反的。这是输出https://godbolt.org

const MyClass::`vftable' DQ FLAT:const MyClass::`RTTI Complete Object Locator'          ; MyClass::`vftable'
    DQ      FLAT:virtual void MyClass::foo(int)
    DQ      FLAT:virtual void MyClass::foo(float)

如果我区分名称(如 foo1 和 foo2),生成代码中的顺序与我的声明中的顺序相同。

对于 C++ 编译器来说,这是正常行为吗?如果是,顺序是如何决定的?


简短的回答是,vtable 的布局肯定是由编译器决定的。事实上,语言标准甚至不要求编译器使用 vtable 来实现虚拟函数调度。

也就是说,在 Windows 和 Visual C++ 的特定情况下:

  • C++ vtable 是经过精心设计的,以便与 COM 调用约定兼容,这要求为虚拟函数顺序分配插槽;

  • 同样对于 COM 互操作,简单继承会在父 vtable 的末尾附加新的虚拟函数;

  • 然而,COM 不允许重载,即具有不同签名的同名函数。

OP 的情况违反了最后一点,因此 COM 保证在这里不适用,因为由于重载,该接口一开始就不兼容 COM。事实上,微软明确警告 C#避免 COM 可见接口中的重载.

因此从技术上讲,VC++ 编译器的行为并没有违反任何规则,无论是语言还是 COM。另外,我不知道有任何选项/技巧/资源可以强制 vtable 中重载的特定顺序。

一种可能的(尽管不太漂亮)解决方法是在继承树中引入一个人为的额外类,以便每个新的派生只添加一个唯一的重载。

struct MyHiddenStruct
{
    virtual void foo(float) = 0; 
};

struct MyStruct : MyHiddenStruct
{
    MyHiddenStruct::foo;
    virtual void foo(int) = 0; 
};

class MyClass : public MyStruct
{
public:
    void foo(float) { }
    void foo(int) { }
};

[ EDIT]   在以下位置找到了类似的 VS 2010 问答vfptr 中的 Visual C++ 方法按相反顺序排列强烈暗示同一类中的重载以与声明相反的顺序分组在 vtable 中。所以无论 VS 2019 现在做什么,这都不是一个新的突发奇想。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

反转生成的 vtable 函数顺序(具有相同名称的函数) 的相关文章

  • boost::asio + std::future - 关闭套接字后访问冲突

    我正在编写一个简单的 TCP 客户端来发送和接收单行文本 异步操作由 std future 处理 以便于超时阻塞查询 不幸的是 我的测试应用程序在破坏服务器对象时因访问冲突而崩溃 这是我的代码 TCP客户端 hpp ifndef TCPCL
  • 如何读取扩展文件属性/文件元数据

    因此 我按照教程使用 ASP net core 将文件 上传 到本地路径 这是代码 public IActionResult About IList
  • std::cout 和 std::wcout 有什么区别?

    在c 中 有什么区别std cout and std wcout 它们都控制流缓冲区的输出或将内容打印到控制台 或者它们只是相似吗 它们作用于不同的字符类型 std cout uses char作为字符类型 std wcout uses w
  • 启动时出现 OData v4 错误:找不到段“Whatever”的资源

    我正在构建新的 v4 服务 一切进展顺利 直到我为新模型 实体添加了新控制器 并在启动站点进行测试运行时收到此错误 控制器似乎编码正确 就像其他控制器一样 控制器 CustomersOData 中的操作 GetFeed 上的路径模板 Cus
  • 如何修复此错误“GDI+ 中发生一般错误”?

    从默认名称打开图像并以默认名称保存 覆盖它 我需要从 Image Default jpg 制作图形 将其放在 picturebox1 image 上并在 picurebox1 上绘制一些图形 它有效 这不是我的问题 但我无法保存 pictu
  • 将内置类型转换为向量

    我的 TcpClient 类接受vector
  • 存储来自其他程序的事件

    我想将其他应用程序的事件存储在我自己的应用程序中 事件示例 打开 最小化 Word 或打开文件时 这样的事可能吗 运行程序 http msdn microsoft com en us library ms813609 aspx and 打开
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • ASP.NET:获取自 1970 年 1 月 1 日以来的毫秒数

    我有一个 ASP NET VB NET 日期 我试图获取自 1970 年 1 月 1 日以来的毫秒数 我尝试在 MSDN 中寻找方法 但找不到任何东西 有谁知道如何做到这一点 从 NET 4 6 开始 该方法ToUnixTimeMillis
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 将 log4net 与 Autofac 结合使用

    我正在尝试将 log4net 与 Autofac 一起使用 我粘贴了这段代码http autofac readthedocs org en latest examples log4net html http autofac readthed
  • 如何编写一个同时需要请求和响应Dtos的ServiceStack插件

    我需要提供本地化数据服务 所有本地化的响应 Dto 都共享相同的属性 IE 我定义了一个接口 ILocalizedDto 来标记那些 Dto 在请求端 有一个ILocalizedRequest对于需要本地化的请求 Using IPlugin
  • gcc 的配置选项如何确定默认枚举大小(短或非短)?

    我尝试了一些 gcc 编译器来查看默认枚举大小是否很短 至少一个字节 强制使用 fshort enums 或无短 至少 4 个字节 强制使用 fno short enums user host echo Static assert 4 si
  • 为什么在setsid()之前fork()

    Why fork before setsid 守护进程 基本上 如果我想将一个进程与其控制终端分离并使其成为进程组领导者 我使用setsid 之前没有分叉就这样做是行不通的 Why 首先 setsid 将使您的进程成为进程组的领导者 但它也
  • 如何在 C# 中调整图像大小同时保持高质量?

    我从这里找到了一篇关于图像处理的文章 http www switchonthecode com tutorials csharp tutorial image editing saving cropping and resizing htt
  • Server.MapPath - 给定的物理路径,预期的虚拟路径

    我正在使用这行代码 var files Directory GetFiles Server MapPath E ftproot sales 在文件夹中查找文件 但是我收到错误消息说 给定物理路径但虚拟路径 预期的 我对在 C 中使用 Sys
  • memset 未填充数组

    u32 iterations 5 u32 ecx u32 malloc sizeof u32 iterations memset ecx 0xBAADF00D sizeof u32 iterations printf 8X n ecx 0

随机推荐

  • 如何在 Spyder 中的所有其他窗口之上显示 matplotlib 图形窗口

    我正在使用 Spyder IDE 我发现 matplotlib 图形窗口总是显示在其他窗口后面 例如 在启动 Spyder 后立即输入plt plot 0 1 0 1 在控制台中 我在 Spyder 主窗口后面看到了一个绘图 如何使新的图形
  • 为什么服务器运行时PHP ftp_connect失败?

    一段时间以来 我一直在尝试通过 FTP 连接到我的服务器 但似乎无法正常工作 connection id ftp connect example com 22 运行此代码时 它会挂起一段时间 直到 PHP 最终告诉我脚本执行时间太长并退出
  • 如何使用 javascript 或 jquery 检查命名窗口是否存在

    这是场景 我在网站的页脚中有一个静态音频播放器 如果您转到另一个页面 音频播放器将重新加载 这不是问题 因为它是音频流 而不是静态文件 该页脚中还有一个链接 单击该链接将导致整个静态页脚消失 并弹出一个包含音频流的窗口 当然 问题是 如果有
  • 如何将 PIL `Image` 转换为 Django `File`?

    我正在尝试转换UploadedFile到 PILImage对象对其进行缩略图 然后转换 PILImage我的缩略图函数返回到的对象File目的 我怎样才能做到这一点 无需写回文件系统 然后通过 open 调用将文件带回内存的方法是使用 St
  • 标签不会显示在 d3 力图上

    我是 d3 的初学者 我发现特别有用且有趣的图表之一是 d3 力图 我一直在尝试它 但由于某种原因 我在这个特定的数据集上遇到了很多麻烦 具体来说 我一直在尝试让标签显示在我的 d3 力图上 但它就是行不通 这是我的代码
  • 需要帮助理解循环

    好吧 我想做的事情看起来相当简单 但它并没有按照我想要的方式工作 我知道我只是没有得到什么 本质上我正在尝试读取控制台输入 并将其分配给一个变量 然后我想检查该变量以查看它是否是有效数字 如果不是 我想告诉用户它是无效的 并重新开始循环 直
  • 变体双亚型超过最大值

    当我查看 变体数据类型 文档时 它说具有 double 子类型的变体可以支持最大 1 79769313486232E308 15 位数字 的正值 并且 当包含货币 小数和双精度值的变体变量超出其各自的范围时 会发生错误 但是 当我运行以下代
  • 如何将带有日期和时间 AM/PM 的字符串转换为 24 小时 mysql 时间戳格式

    我正在尝试从具有以下内容的字符串将日期和时间插入 mysql 日期时间字段日 月 年 时 分 秒 上午 下午 format 20 10 2014 05 39 PM 20 10 2014 05 39 AM 我知道 MYSQL 时间戳格式是 y
  • 针对 Access 数据库的 pyodbc 查询出现“可选功能未实现”错误

    对于任何可以提供帮助的人 提前表示感谢 我正在运行 64 位 Windows 10 64 位 Office 和 64 位 python 3 7 2 使用 pyodbc 我尝试执行如下所示的 Select 语句 SELECT FROM Eco
  • Flutter中如何动态生成多个Dropdown?

    我有 Java 背景 对 Flutter 很陌生 我陷入了需要动态创建多个下拉列表的场景 例如 有一项披萨优惠提供 2 个大披萨 2 个小披萨和 1 份饮料 因此 每当顾客选择任何披萨时 他 她必须选择一种口味 如果有 2 个大披萨 我需要
  • Chart.js v2:甜甜圈内甜甜圈之间的空间

    我正在使用 Chart js v2 5 0 我把甜甜圈放在甜甜圈里面 我想要两个甜甜圈之间的距离 A 变大而不影响同一甜甜圈内切片之间的距离 B 请看下图 目前我正在使用该房产边框宽度 然而 这也会影响宽度B 请看下面的代码 options
  • 为什么 akka 需要不可变消息

    或者换句话说 可变消息是否有正确的用途 我面临的用例是我想要处理基本上属于类型的对象 Map
  • SimpleHttpOperator Airflow,数据模板化

    我正在尝试正确渲染data里面一个SimpleHttpOperator在 Airflow 中 并通过我发送的配置dag run result SimpleHttpOperator task id schema detector http c
  • `%in%` 和 `==` 有什么区别?

    df lt structure list x 1 10 time c 0 5 0 5 1 2 3 0 5 0 5 1 2 3 Names c x time row names c NA 10L class data frame df df
  • 关于Struts2中的Action映射 - 没有映射Action

    我正在尝试运行我的 struts 应用程序 但收到错误操作未映射我已经看到名称空间是正确的 但仍然收到错误 struts xml
  • 响应式 2 列 CSS 布局,包括固定宽度的侧边栏?

    在任何地方都找不到这个问题的解决方案 我猜这一定是一个非常常见的问题 我正在创建一个带有侧边栏的响应式设计 其中侧边栏需要具有 200px 的固定宽度 并且高度未知 我怎样才能使主要内容区域占据所有剩余宽度 而不会出现任何异常行为 我最接近
  • 如果 scalatest 中的 FunSpec 的 afterEach 测试失败,如何确定

    在使用 FunSpec 的 scalatest 中 我有一些在 afterEach 中触发的代码 我想仅在测试失败时执行一些代码来获取屏幕截图 我所看到的几乎所有内容都试图通过将断言放入 try 块中来解决这个问题 这看起来很糟糕 Test
  • 如何等待回调函数返回?

    我正在使用phonegap 制作一个android 应用程序 我正在使用phonegap 的Storage api 来查询数据库 这是我的代码 function directPath src dest var db window openD
  • 自动调整文本输入框html大小

    我创建了一个输入 键入文本 框并使其自动调整大小非常简单 但是 有一些我似乎无法修复的故障 当我开始打字时 盒子缩小了一点 当我按退格键 或方向箭头 时 该框首先展开 然后在我继续键入时缩小 这是我的代码 function Expander
  • 反转生成的 vtable 函数顺序(具有相同名称的函数)

    如果使用 Visual Studio 2019 我使用两个具有相同名称但不同参数的虚拟方法来编译此 C 代码 struct MyStruct virtual void foo float 0 virtual void foo int 0 c