C++中为什么派生类的构造函数要初始化虚拟基类?

2024-01-06

我的理解,比如阅读this, https://www.cprogramming.com/tutorial/virtual_inheritance.html是派生类的构造函数不调用其虚拟基类的构造函数。

这是我做的一个简单的例子:

class A {
    protected:
        A(int foo) {}
};

class B: public virtual A {
    protected:
        B() {}
};

class C: public virtual A {
    protected:
        C() {}
};

class D: public B, public C {
    public:
        D(int foo, int bar) :A(foo) {}
};


int main()
{
    return 0;
}

由于某种原因,构造函数B::B() and C::C()正在尝试初始化A(按照我的理解,它应该已经被初始化了D在此刻):

$ g++ --version
g++ (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ test.cpp
test.cpp: In constructor ‘B::B()’:
test.cpp:8:13: error: no matching function for call to ‘A::A()’
    8 |         B() {}
      |             ^
test.cpp:3:9: note: candidate: ‘A::A(int)’
    3 |         A(int foo) {}
      |         ^
test.cpp:3:9: note:   candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr A::A(const A&)’
    1 | class A {
      |       ^
test.cpp:1:7: note:   candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr A::A(A&&)’
test.cpp:1:7: note:   candidate expects 1 argument, 0 provided
test.cpp: In constructor ‘C::C()’:
test.cpp:13:13: error: no matching function for call to ‘A::A()’
   13 |         C() {}
      |             ^
test.cpp:3:9: note: candidate: ‘A::A(int)’
    3 |         A(int foo) {}
      |         ^
test.cpp:3:9: note:   candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr A::A(const A&)’
    1 | class A {
      |       ^
test.cpp:1:7: note:   candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr A::A(A&&)’
test.cpp:1:7: note:   candidate expects 1 argument, 0 provided

我确信我误解了或者做错了一些非常基本的事情,但我不知道是什么。


虚拟基的构造函数is建。它是有条件建造的。即最底层派生类的构造函数调用虚基类的构造函数。如果 - 这是条件 - 具有虚拟基类的派生类不是构造对象的具体类,那么它不会构造虚拟基类,因为它已经由具体类构造了。但否则它将构建虚拟基地。

因此,您必须在所有派生类的构造函数中正确初始化虚拟基类。您必须知道,如果具体类不是您正在编写的类,则不一定会发生特定的初始化。编译器不知道也不可能知道您是否会创建这些中间类的直接实例,因此它不能简单地忽略它们损坏的构造函数。

如果您将这些中间类抽象化,那么编译器就会知道它们永远不是最具体的类型,因此不需要它们的构造函数来初始化虚拟基类。

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

C++中为什么派生类的构造函数要初始化虚拟基类? 的相关文章

随机推荐

  • 数组索引超出范围的二维数组

    我有一个二维数组 但没有 行数为 1 并且没有 列数 gt 1 double T new double 1 24 System out println T 1 length 但是当我打印列的长度时 它说索引超出范围 但是当我打印以下内容时
  • Android停止录音失败

    我将启动一项服务来开始录音 当我试图停止时 它显示以下消息 06 27 17 21 30 138 E MediaRecorder 6122 stop called in an invalid state 0 我不确定其他功能 例如上传数据到
  • Symfony 表单事件将错误添加到特定字段

    我的场景如下 如果用户从 maxRedemptionForDiscount 中选择 true 并在 maxRedemptionForDiscountValue 中输入 0 则应该有一条错误消息呈现到特定字段 在 TextType 字段的位置
  • 打印机忽略 javax.print.attribute.PrintRequestAttributeSet 选项

    我必须使用 javax print api 打印文件 纯文本 我能够查找打印机并提交打印作业 但我只能打印该文件的一份副本 下面是我一直在使用的代码 打印机无法识别我使用 PrintRequestAttributeSet 指定的任何选项 属
  • 安装的构建工具修订版 28.0.3 已损坏。如何修复此错误

    当我创建一个新项目时 然后构建项目或尝试在模拟器中运行应用程序 使用 sdk api level 28 Android 9 0 Pie 构建输出窗口总是显示此错误 Installed Build Tools revision 28 0 3
  • 创建新线程的测试方法以及我们从事件中获得的结果(NUnit 2.6)

    我的课程有一个公共方法Start 一个私有方法和一个事件Finishing Start call new Thread private method 私有方法使用事件返回值 当这个方法完成工作后 再调用这个事件 现在我想为这个类编写测试 如
  • BASH 脚本暂停/继续脚本内的进程

    在我正在编写的 bash 脚本中 我试图在后台启动一个进程 睡眠 然后挂起它 最后 该过程完成 由于某种原因 当我发送带有停止信号的kill命令时 它只是继续运行 就好像它没有收到任何消息一样 我可以从命令行执行此操作 但 bash 脚本未
  • 应用程序可以在 Android 和 IOS 模拟器中运行,但在发布后不能运行

    Problem 我创建了一个应用程序 它是 MQTT 代理客户端 当我使用 iOS Android 模拟器进行开发时 我与代理的连接工作正常 但是 当我发布 apk 版本时 我的应用程序无法连接 它有套接字问题 AMQJS0007E 套接字
  • 如何在Python中使用OpenSSL从pfx文件中提取密钥?

    我需要签署一份xml与certificate and key from a pfx file 换句话说 我有一个 pfx 文件 我需要从其中提取pem an key签署我的xml 我发现这个脚本可以从 pfx 中提取笔和密钥 但出现错误 i
  • 任意多边形的宽度

    我需要一种方法来表征二维点集的大小 这样我就可以根据视口的比例来确定是否将它们渲染为空间中的单个点或代表性多边形 我已经有一个算法来计算该集合的凸包以生成代表性多边形 但我需要一种方法来表征其大小 一个明显的衡量标准是凸包上点之间的最大距离
  • 子类化 beautifulsoup html 解析器,出现类型错误

    我使用 beautifulsoup 很棒的 html 解析器编写了一个小包装器 最近 我尝试改进代码并使所有 beautifulsoup 方法直接在包装类中可用 而不是通过类属性 我认为子类化 beautifulsoup 解析器将是实现此目
  • 使用 CoreGraphics 在视网膜显示屏上绘图 - 图像像素化

    在我的 iOS 应用程序中 我尝试使用 CoreGraphics 绘制曲线 绘图本身工作正常 但在视网膜显示器上 图像是使用相同的分辨率绘制的 并且像素不会加倍 结果是像素化图像 我正在使用以下函数进行绘图 void touchesMove
  • 如何全局更改Android首选项图标颜色

    我已经为我的所有首选项设置了平面图标 我想全局更改该图标的颜色 当我尝试下面的代码时 它甚至改变了工具栏中的后退按钮颜色 我只想全局更改首选项图标色调 预先感谢
  • C++ 抽象类不能有带有该类参数的方法

    我创建了这个 h 文件 pragma once namespace Core class IComparableObject public virtual int CompareTo IComparableObject obj 0 但编译器
  • django.core.exceptions.ImproperlyConfigured:无法使用视图名称“用户详细信息”解析超链接关系的 URL

    TL DR 我收到此错误 但不知道原因 django core exceptions ImproperlyConfigured 无法使用视图名称 user detail 解析超链接关系的 URL 您可能未能在 API 中包含相关模型 或者错
  • 关闭移动 Safari 中的表单助手?

    当在触摸屏设备上运行时 在我的情况下是iPhone 但我认为它在其他设备上也会这样做 当弹出表单字段的虚拟键盘时 键盘顶部会添加导航按钮 上一个 下一步 完成 有时是 自动填充 这显然是Mobile Safari 的 表单助手 我觉得这是多
  • 哪些客户端内缓存选项适合 Cassandra 和 Java?

    我目前正在构建一个必须能够处理每秒数万次写入的系统 我或多或少决定使用 Apache Cassandra 作为持久层 并将使用 Java 作为应用程序层 但在某些情况下 我需要以在几秒钟内获取任何更改的方式快速访问数据 每次我需要检查这些数
  • 使用 add() 方法添加片段不会隐藏以前的片段

    使用 add 方法添加新片段时 我遇到 意外行为 我想在 FrameLayout 上添加一个新片段 但是当我这样做时 前一个片段仍然可见 这是使用 add 方法时的预期结果吗 是因为我使用的是 FrameLayout 并且 add 方法只是
  • 当 MasterPage 位于根文件夹中时在子文件夹中使用 JQuery

    我试图在 ASP NET 中名为 samples 的子文件夹中使用 jquery 库 其中母版页位于根目录中 目前 对 jquery 脚本的引用位于母版页的 head 标签中 如果我创建的页面也在根目录中 则一切正常 如果我将页面移动到 s
  • C++中为什么派生类的构造函数要初始化虚拟基类?

    我的理解 比如阅读this https www cprogramming com tutorial virtual inheritance html是派生类的构造函数不调用其虚拟基类的构造函数 这是我做的一个简单的例子 class A pr