虚拟调度实施细节

2023-12-24

首先,我想明确的是我确实明白 C++ 标准中没有 vtable 和 vptrs 的概念。然而,我认为几乎所有实现都以几乎相同的方式实现虚拟调度机制(如果我错了,请纠正我,但这不是主要问题)。另外,我相信我知道虚拟函数是如何工作的,也就是说,我总是可以知道将调用哪个函数,我只需要实现细节。

假设有人问我以下问题:
“您有带有虚拟函数 v1、v2、v3 的基类 B 和派生类 D:B,它重写函数 v1 和 v3 并添加虚拟函数 v4。请解释虚拟调度的工作原理”。

我会这样回答:
对于每个具有虚函数的类(在本例中为 B 和 D),我们有一个单独的函数指针数组,称为 vtable。
B 的 vtable 将包含

&B::v1
&B::v2
&B::v3

D 的 vtable 将包含

&D::v1
&B::v2
&D::v3
&D::v4 

现在B类包含一个成员指针vptr。 D 自然地继承了它,因此也包含了它。在 B 的构造函数和析构函数中,B 设置 vptr 指向 B 的 vtable。在D的构造函数和析构函数中,D将其设置为指向D的vtable。
对多态类 X 的对象 x 上的虚函数 f 的任何调用都被解释为对 x.vptr[f 在 vtable 中的位置] 的调用

问题是:
1.以上描述是否有错误?
2.编译器如何知道f在vtable中的位置(请详细说明)
3. 这是否意味着如果一个类有两个基数,那么它就有两个 vptr?在这种情况下发生了什么? (尝试以与我类似的方式描述,尽可能详细)
4. A 在顶部 B、C 在中间、D 在底部的钻石层次结构中会发生什么? (A是B和C的虚拟基类)

提前致谢。


1.以上描述是否有错误?

都好。 :-)

2.编译器如何知道f在vtable中的位置

每个供应商都有自己的方法来做到这一点,但我总是将 vtable 视为成员函数签名到内存偏移量的映射。所以编译器只维护这个列表。

3. 这是否意味着如果一个类有两个基数,那么它就有两个 vptr?在这种情况下发生了什么?

通常,编译器会组成一个newvtable,由按指定顺序附加在一起的所有虚拟基址的 vtable 以及虚拟基址的 vtable 指针组成。他们遵循派生类的 vtable 函数。这是极其供应商特定的,但对于class D : B1, B2,你通常会看到D._vptr[0] == B1._vptr.

该图像实际上用于组成对象的成员字段,但编译器可以以完全相同的方式组成虚函数表(据我所知)。

4. A 在顶部 B、C 在中间、D 在底部的钻石层次结构中会发生什么? (A是B和C的虚拟基类)

简短的回答?绝对的地狱。您实际上继承了这两个基础吗?只是其中之一吗?他们都不是?最终,使用了为类编写 vtable 的相同技术,但是如何完成此操作的方式差异很大,因为how应该这样做并不是一成不变的。解决钻石层次结构问题有一个不错的解释here http://www.phpcompiler.org/articles/virtualinheritance.html,但是,像大多数这样,它是特定于供应商的。

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

虚拟调度实施细节 的相关文章

  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • 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
  • 推导指南中的引用和值之间的差异

    考虑类型A template
  • 将内置类型转换为向量

    我的 TcpClient 类接受vector
  • 在 C# 中循环遍历文件文件夹的最简单方法是什么?

    我尝试编写一个程序 使用包含相关文件路径的配置文件来导航本地文件系统 我的问题是 在 C 中执行文件 I O 这将是从桌面应用程序到服务器并返回 和文件系统导航时使用的最佳实践是什么 我知道如何谷歌 并且找到了几种解决方案 但我想知道各种功
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • 无法在 Windows 运行时组件库的 UserControl 中创建依赖项属性

    我想在用户控件内创建数据可绑定属性 这个用户控件包含一个 Windows 运行时组件 项目 我使用下面的代码来创建属性 public MyItem CurrentItem get return MyItem GetValue Current
  • 如何在 C# 中定义文本框数组?

    您好 当我在 Windows 申请表上创建文本框时 我无法将其命名为 box 0 box 1 等 我这样做的目的是因为我想循环使用它们 其实我发现TextBox array firstTextBox secondTextBox 也有效
  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n
  • 未定义的行为或误报

    我 基本上 在野外遇到过以下情况 x x 5 显然 它可以在早期版本的 gcc 下编译干净 在 gcc 4 5 1 下生成警告 据我所知 警告是由 Wsequence point 生成的 所以我的问题是 这是否违反了标准中关于在序列点之间操
  • 在一个字节中存储 4 个不同的值

    我有一个任务要做 但我不知道从哪里开始 我不期待也绝对不想要代码中的答案 我想要一些关于该怎么做的指导 因为我感到有点失落 将变量打包和解包到一个字节中 您需要在一个字节中存储 4 个不同的值 这些值为 NAME RANGE BITS en
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • HttpWebRequest 在第二次调用时超时

    为什么以下代码在第二次 及后续 运行时超时 代码挂在 using Stream objStream request GetResponse GetResponseStream 然后引发 WebException 表示请求已超时 我已经尝试过
  • gcc 的配置选项如何确定默认枚举大小(短或非短)?

    我尝试了一些 gcc 编译器来查看默认枚举大小是否很短 至少一个字节 强制使用 fshort enums 或无短 至少 4 个字节 强制使用 fno short enums user host echo Static assert 4 si
  • 如何在按钮单击时模拟按键 - Unity

    我对 Unity 中的脚本编写非常陌生 我正在尝试创建一个按钮 一旦单击它就需要模拟按下 F 键 要拾取一个项目 这是我当前的代码 在编写此代码之前我浏览了所有统一论坛 但找不到任何有效的东西 Code using System Colle
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • Linq-to-entities,在一个查询中获取结果+行数

    我已经看到了有关此事的多个问题 但它们已经有 2 年 或更长 的历史了 所以我想知道这方面是否有任何变化 基本思想是填充网格视图并创建自定义分页 所以 我还需要结果和行数 在 SQL 中 这将类似于 SELECT COUNT id Id N
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub

随机推荐