虚拟继承的内部机制

2024-01-22

C++ 示例代码:

class A {
  public:
    A(int) {}
};

class B : public virtual A {
  public:
    B(int b) : A(b) {}
};

class C : virtual public A {
  public:
    C(int c) : A(c) {}
};

class D : public B, public C {
  public:
    D() : B(1), C(2){};
};

这是钻石问题的典型代码(解决方案)。我知道为什么使用 virtual 关键字。但我不知道编译器处理该问题的内部机制。现在我遇到了关于上述机制的两种不同的理论,如下所述。

  1. 当使用 virtual 关键字继承一个类时,编译器会在派生类中添加一个虚拟基指针。我已经检查了派生类的大小,是的,它包括附加指针的大小。但我不知道在上面的示例中,当 A 类的成员在 D 类中引用时,它指向哪里以及它如何工作。

  2. 对于每个构造函数,编译器都会为程序员提供的每个定义创建两个版本。认识自这个链接 https://stackoverflow.com/questions/6921295/dual-emission-of-constructor-symbols例如在上面的代码中。 编译器会生成2个版本的C构造函数

     C(int){}           // Version1
    
     C(int):A(int){}    // Version2 
    

    以及构造函数 B 的两个不同版本

     B(int){}           // Version1
    
     B(int):A(int){}    // Version2
    

    因此,当构造 D 时,编译器将生成以下代码之一

    D() : B(), C(2) {}  // Version1
    
    D() : B(1), C() {}  // Version2
    

    从而确保只创建 A 的一个实例,从而避免 A 的重复副本。

请帮助我理解内部机制。


常见的用法(任何标准都没有指定!)是首先创建虚拟继承对象的实例,并将指向该实例的指针放入 vtable 中。所以这就是发生的事情:

  • 创建 AN:没什么特别的
  • 创建 B:构造 A 并将其链接添加到 B vtable 中
  • 创建 D:首先构造 A,然后构造 B 和 C,并且每个都在其 vtable 中包含指向 A 的链接。这允许当您获得指向 D 对象的指针时,将其转换为指向 B 和 C 的指针,并且每个指针仍然知道其 A 成员在哪里。

但这只不过是对可能实现的理论答案。我并不是说实际的实现(例如 gcc、clang 或 microsoft vc)完全遵循这一点。但是,例如,如果您必须用纯 C 语言模拟虚拟继承,则可以使用它。

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

虚拟继承的内部机制 的相关文章

  • 如何将 Pandas Dataframe 中的字符串转换为字符列表或数组?

    我有一个名为的数据框data 其中一列包含字符串 我想从字符串中提取字符 因为我的目标是对它们进行一次性编码并使之可用于分类 包含字符串的列存储在预测因子如下 predictors pd DataFrame data columns Seq
  • 将数组从 .npy 文件读入 Fortran 90

    我使用 Python 以二维数组 例如 X 的形式生成一些初始数据 然后使用 Fortran 对它们进行一些计算 最初 当数组大小约为 10 000 x 10 000 时 np savetxt 在速度方面表现良好 但是一旦我开始增加数组的维
  • Python 中的迭代器 (iter()) 函数。 [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 对于字典 我可以使用iter 用于迭代字典的键 y x 10 y 20 for val in iter y print val 当
  • 是否可以使用环境变量来为基于 log4net 的日志系统指定所需的日志级别?

    我们使用 log4net 进行日志记录 我想知道在指定日志级别时是否可以使用环境变量 动机很简单 我们的 QA 人员不必编辑配置文件 他们只需设置一次特定的环境变量 简而言之 我们不想将配置文件中的日志级别设置为某个恒定值 因为相同的构建由
  • 如何获取本地文件系统上 docker 容器生成的内容(最小失败示例)

    这个问题是另一个问题的最小失败版本 如何获取本地文件系统上docker容器生成的内容 https stackoverflow com questions 34924011 how to get contents generated by a
  • 从 Android 中的过渡动画中排除 BottomNavigation

    我一直在四处寻找 但找不到有助于解决这个特定问题的答案 我的应用程序有一个自定义滑入 滑出效果 如下所示 Intent intent new Intent getApplicationContext MyActivity class sta
  • GKE 出现错误:ImagePullBackOff 和错误:ErrImagePull 错误

    当 kubectl 应用 yaml 将自定义构建的 docker 映像部署到 GCP 中的集群 编辑掉敏感信息 时 我收到以下错误 已尝试以下但没有运气 手动部署镜像 检查以确保防火墙规则允许 443 并且没有任何东西阻止它 尝试将容器注册
  • linux下无法安装Cairo包

    我在本地下载该软件包并尝试安装它 但出现此错误 R CMD INSTALL l usr local lib64 R library Cairo 1 5 1 tar gz 我得到他的错误 checking for PNG support in
  • 在地图上使用 find

    如何使用 find 和 aconst iterator如果你有一个地图定义为 typedef std pair
  • 如何使用 Spring AOP 建议静态方法?

    在执行类的静态方法之前和之后需要完成一些日志记录 我尝试使用 Spring AOP 来实现这一点 但它不起作用 而对于正常方法来说它起作用 请帮助我理解如何实现这一点 如果可以使用注释来完成 那就太好了 也许您应该在使用 Spring AO
  • 确定分区属于什么文件系统

    操作系统如何知道分区正在使用什么文件系统 换句话说 FAT16 32 NTFS ext2 3等如何区分 如果您在 Windows 上使用 Win32 API 则可以调用 GetVolumeInformation http msdn micr
  • 如果列表在初始化之前为空,则 jQuery 可排序无法与水平列表正常工作

    如果我在初始化后将元素添加到列表中 sortable它无法正常工作 参见示例jsFiddle http jsfiddle net NQMPr 1 示例 HTML div class container div br
  • 使用 Getopt::Long 解析参数的最简洁方法

    我使用 GetOpt 来解析命令行参数 我想添加一个新选项 multi 它应该得到一个如下所示的字符串 key1 abc key2 123 key3 xwz 我不知道用户想要提供多少个自定义密钥 但他可以提供 minimax5键 另外 我想
  • 将 Zurb Foundation v5 升级到 v6.2 所需的工作

    将 Foundation 5 升级到 6 2 需要做什么工作以及需要做多少工作 我们的开发工作室正在接管现有 F5 项目的开发 看起来前端布局已经完成了 80 尽管我们可能会过渡到 JSX 但几乎没有什么会保持不变 我需要帮助来权衡 F6
  • 如何将 configmap 附加到 Kubernetes 中的部署?

    根据此处找到的说明 https kubernetes io docs tasks access application cluster connecting frontend backend https kubernetes io docs
  • 使用 lpSolve 优化 R 团队名单

    我是 R 新手 有一个想要解决的特定幻想运动队优化问题 我见过其他帖子使用 lpSolve 来解决类似的问题 但我似乎无法理解代码 下面的示例数据表 每个球员都在一个球队中 扮演着特定的角色 有薪水 并且每场比赛都有平均得分 我需要的限制是
  • C#“var”关键字在 VB.NET 中的等价物是什么?

    例如 我如何获得 VB NET静态类型局部变量是static赋值右侧的表达式的类型 像这样 Dim http msdn microsoft com en us library 7ee5a7s1 aspx我的变量 3 你还需要 选项推断 ht
  • 滑动时向 PageView 添加新页面

    我目前正在制作一个日历应用程序 我想向右或向左滑动以转到下个月或上个月 我使用 PageView 时首先设置了一个包含 3 个项目的数组 第一个页面是第二个项目 我想向右滑动并在末尾添加一个页面 我想向左滑动并在开头添加一个页面 目前 如果
  • 从 Flask 中的 S3 返回 PDF

    我正在尝试在 Flask 应用程序的浏览器中返回 PDF 我使用 AWS S3 来存储文件 并使用 boto3 作为与 S3 交互的 SDK 到目前为止我的代码是 s3 boto3 resource s3 aws access key id
  • Golang 优雅地关闭 HTTP 服务器并进行错误处理

    我正在让我的 HTTP 服务器正常关闭 我从帖子中获取了提示here https stackoverflow com questions 39320025 how to stop http listenandserve 并且到目前为止已经像

随机推荐

  • 如何在 Swift 中加载 UIWebView 中的 URL?

    我有以下代码 UIWebView loadRequest NSURLRequest URL NSURL string google ca 我收到以下错误 NSURLRequest 无法转换为 UIWebView 知道问题是什么吗 加载请求
  • Angular2 - “无法绑定到‘ngSwitchWhen’,因为它不是‘模板’的已知属性。”

    我收到以下错误 无法绑定到 ngSwitchWhen 因为它不是 模板 的已知属性 我读过不同的主题 建议添加 从 angular common 导入 CommonModule 并将 CommonModule 添加到 NgModel的导入部
  • Xcode 8 beta 6 - 架构的冲突值

    我尝试使用 Xcode beta 6 在设备上安装我的应用程序 但它在链接阶段失败并出现以下错误 ld linking module flags Objective C Class Properties IDs have conflicti
  • 应用两个数据框

    我正在使用 R 并且我有两个 data frames A and B 它们都有 6 行 但是A有 25000 个列 基因 并且B有 30 列 我想应用一个带有两个参数的函数f x y where x是每一列A and y是每一列B 到目前为
  • C# 将列表拆分为 n 组的所有组合 - 来自 Python 的代码迁移

    我所追求的算法有一个很好的实现here https stackoverflow com questions 39192777 python split a list into n groups in all possible combina
  • 扩展 Laravel 核心日志记录

    我回来时遇到了更多 Laravel 问题 因为我在理解事物方面遇到了问题 再次 我尝试创建一个包来进行我自己的日志记录 在进行了一些额外的阅读 浏览核心代码并尝试其他方法之后 我得出的结论是 我需要做的就是扩展 laravel 日志记录的核
  • 加载内容后显示引导模式

    我正在使用 Bootstrap 3 模式 其中我从 getJson 函数加载一些数据 由于模式内的数据加载速度不一样快 我想显示加载图像 文本 加载所有数据后 然后显示 打开模式 我找到了这个Thread https stackoverfl
  • Html显示格式化文本

    我必须在 html 页面上显示一堆文本 文本看起来像这样 001 This is a Line 00 12 04 002 003 Everthing looks good so far 文本是 预先格式化的 包含大量空格和破折号 每行都具有
  • JQuery 到 asmx 在 Windows 2008 R2 SP1 上失败

    自从安装 SP1 以来 我们在从 JQuery 客户端代码调用 asmx 页面时遇到了问题 IIS 将 JQuery post 调用指向他的默认 404 页面 我们对环境进行了角色恢复 断言此问题是由 SP1 引起的 并且测试证实了这一点
  • mongodb-java POJO不返回id

    我是 MongoDB 的新手 在这里有点疯狂 我正在使用最新的 mongo java driver 版本和 dropwizard 我使用 POJO 写入 DDBB 它有效 但是 当尝试获取元素时 我没有得到实际的 id 这是我尝试过的 DD
  • 如何在数字的最后三位数字之前插入小数点?

    我有一个数字 需要添加小数以进行格式化 该数字保证在 1000 到 999999 之间 我已经以其他方式介绍了其他可能性 这是我无法理解的 我需要在最后 3 位数字之前添加小数 例如 1000 gt 1 000 23513 gt 23 51
  • 我可以向 HTML 标记添加自定义属性吗?

    我可以向 HTML 标记添加自定义属性吗 如下所示
  • 在 Google App Engine 中创建表单自动完成

    我想为标签字段构建一个自动完成功能 就像 App Engine 上的 SO 一样 知道我应该如何进行这个过程吗 服务器端算法 自动完成应该有什么逻辑 应用程序引擎实施 数据存储架构应该是什么 嘿 几天前我就遇到了这个问题 只要您有想要搜索的
  • 如何在 ASP.Net Core Razor 页面中返回带有模型的页面

    如何重定向到页面并传递其模型 就像我们在 MVC 中所做的那样return View model MyModel 我尝试过的 return RedirectToPage Notify new Model notifierVM 注意 我要返回
  • 如何立即关闭 C 程序?

    我正在编写 C 代码 在其中分析一些数据 我已将程序设置为仅处理 100 个数据输入 当输入超过 100 个时 就会出现分段错误 我想创建一种方法 以便当输入数量超过 100 时 用户将收到警告并且程序将终止 我知道如何从主要功能中简单地做
  • MyGroups 未在 Communicator.UIAutomation 中实现

    我正在开发一个浏览器外的 Silverlight 应用程序 它提供了一些 MS Office Communicator 2007 控件 我正在使用 与 SDK 一起安装的文档指出 IMessenger2 界面中有一个 MyGroups 属性
  • 测试 swift 异步函数超时

    如何编写一个单元测试来检查异步函数是否不会超时 我正在尝试常规XCTestExpectation 但是因为await暂停一切 是等不到期待 在下面的代码中 我正在检查loader perform 执行时间不超过1秒 func testLoa
  • 在 KnockoutJS 中获取可观察的多维数组(对象)

    我正在使用 Knockout 构建一个应用程序 发现它非常有用 虽然 我在获取多维数组 对象 可观察时遇到问题 目前我正在使用以下结构 self form ko observableArray ko utils arrayMap initi
  • /bin/sh: python: 找不到命令

    我刚刚安装了 Python3 和 Komodo 我正在尝试运行一个简单的脚本 但收到 py 命令未找到的错误 我对 Komodo 和 Python 都是新手 所以不知道该去哪里寻找 我看到另一篇文章也有同样的问题 但没有提供有帮助的解决方案
  • 虚拟继承的内部机制

    C 示例代码 class A public A int class B public virtual A public B int b A b class C virtual public A public C int c A c clas