问题标签 [virtual-inheritance]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
185 浏览

c++ - 虚拟继承和委托实现

我正在开发一个供内部和外部使用的 api。在 Visual Studio 10 上。

我有一个虚拟基类 IA 和一个派生的虚拟基类 IB。我用 A 类实现 IA,然后从 B 派生出 IB 的具体实现。据我了解,这是经典的钻石问题。因此,我将 IA 的 A 继承设为虚拟,并且将 A 的 Bs 继承设为相同。但我收到警告 c4250(warning C4250: 'B' : inherits 'A::A::AnInt' via dominance)

  • 虽然此警告接缝表明编译器正在执行我想要的操作,但我对警告感到不舒服,并希望确保#pragma 退出是安全的,或者存在一些我不知道的问题。

编码


问题的第二部分。如果您正在创建一个 api,消费开发人员将无法更改相关抽象类。您应该避免设计带有继承的接口,还是继续让派生类使用虚拟继承。

0 投票
1 回答
17606 浏览

c++ - 为什么在虚拟继承中调用默认构造函数?

我不明白为什么在下面的代码中,当我实例化一个类型的对象时daughter,会调用默认grandmother()构造函数?

我认为grandmother(int)应该调用构造函数(以遵循我的mother类构造函数的规范),或者由于虚拟继承,这段代码根本不应该编译。

这里编译器grandmother在我背后默默地调用默认构造函数,而我从未要求过它。

0 投票
1 回答
589 浏览

c++ - How does the virtual inheritance table work in g++?

I'm trying to get a better understanding how virtual inheritance works in practice (that is, not according to the standard, but in an actual implementation like g++). The actual question is at the bottom, in bold face.

So, I built myself a inheritance graph, which has among other things, these simple types:

(In the whole hierarchy I also have a C: virtual A and BC: B,C, so that the virtual inheritance makes sense.)

I wrote a couple of functions to dump the layout of instances, taking the vtable pointer and printing the first 6 8-byte values (arbitrary to fit on screen), and then dump the actual memory of the object. This looks something like that:

Dumping an A object:

Dumping a B object and where the A object is located, which is indicated by printing a lot As at the respective position.

As you can see, the A part of B is located at an offset of 16 bytes to the start of the B object (which could be different if I had instantiated BC and dyn-casted it to a B*!).

I would have expected the 16 (or at least a 2, due to alignment) to show up somewhere in the table, because the program has to look up the actual location (offset) of A at runtime. So, how does the layout really look like?


Edit: The dump is done by calling dump and dumpPositions:

0 投票
2 回答
3747 浏览

c++ - 虚拟继承和可怕的钻石

我很难解决可怕的钻石问题。提醒一下,这里是这个问题的经典类层次结构:

为了解决这个问题,标准的解决方案是让 C1 和 C2 使用虚拟继承从 B 继承。

我的问题是 B 和 C1 来自我无法修改的 SDK。 下面的示例我无法让SubClassB虚拟地从Base继承。类:PureVirtualBase、Base 和 SubClassB 来自我使用的 SDK。我无法修改它们。SubClassA 和 Leaf 是我的自定义类。我可以改变它们。

在这种情况下,无法将SubClassB更改为使用来自Base的虚拟继承。应该怎么做:

  • Leaf实例只包含一个Base
  • 在尝试访问在PureVirtualBase中定义的纯虚拟函数并在Base中实现时避免歧义
  • 如果我评论对 f_PurevirtualBase 的调用,它会编译,但我有一个警告, 由于模棱两可,'Leaf' 中的虚拟基础'Base' 不可访问如果我取消注释此调用:我收到此错误:对成员'f_PureVirtualBase' 的请求不明确
  • 如果我在这个调用前面加上类名(myleaf.SubClassA::f_PureVirtualBase() 那么它可以工作,但显然有问题,因为叶子 对象中包含2 个Base )。

有什么提示吗?

更多信息以回答评论

我的目标架构比我在原始问题中提供的示例稍微复杂一些:

LeafOne:继承自 SubClassA 和 SubClassB(SDK)

LeafTwo : 继承自 SubClassA 和 SubClassC(SDK)

LeafThree:继承自 SubClassA 和 SubClassD(SDK)

SubClassA 是我自己的私有代码。它提供自定义功能。SDK 方法应该能够将其视为 Base 实例。 此类不会被实例化,但它可以在执行某些处理时同时处理 LeafOne、LeafTwo 和 LeafThree。

0 投票
5 回答
302 浏览

c++ - 使用姐妹继承

让我们假设一些无法触及的(遗留)代码声明

让我们假设有

是否可以在不显式调用 f() 的情况下进行 A 子类调用 B::f,即代替

有类似的东西

(注意最后一个类是抽象的,因为编译器 A::f 没有定义)

0 投票
1 回答
1560 浏览

c++ - C ++中的虚拟与非虚拟多重继承

我正在尝试掌握 C++ 中多重虚拟/非虚拟继承的概念。如果我理解正确,如果类 B 和 C 虚拟继承自类 A,它们共享一种单例对象,即它们都访问一个公共对象 A 的相同字段。多重继承将为任何 B 和 C 对象创建单独的 A 对象。

考虑到上述情况,会有人如此友善并在一个简单实用的背景下呈现它吗?为什么首先要进行多重继承,然后为什么要使用虚拟/非虚拟?

谢谢。

0 投票
1 回答
1938 浏览

c++ - 虚拟多重继承 - 最终覆盖

在尝试更深入地分析 C++ 的继承机制时,我偶然发现了以下示例:

以上,不知何故,编译并调用 Right::f()。我看到编译器中可能发生的事情,它知道有一个共享的 Base 对象,并且 Right 覆盖 f(),但实际上,在我的理解中,应该有两种方法:(Left::f()继承自Base::f())和Right::f(),覆盖Base::f(). 现在,我认为,基于 Bottom 继承了两个单独的方法,它们都具有相同的签名,应该会有冲突。

谁能解释 C++ 的哪个规范细节处理这种情况以及它是如何从低级别的角度来处理的?

0 投票
0 回答
152 浏览

c++ - 这是对虚拟继承的一种很好的利用吗?

我想跟踪一些选定类的对象的删除,类代码本身的变化很小。

我考虑过重载delete运算符(全局),但它要求我的重载delete存在于所有编译单元中,在我的情况下这可能很麻烦。此外,如果创建了跟踪对象的数组,我将不得不重载delete[]运算符,但不幸的是,在该重载代码中没有标准方法可以知道数组的长度以及正在销毁的对象数量。我也可以重载new[]运算符并跟踪分配及其长度,但它看起来不是一个干净的解决方案,并且遇到delete[]运算符的相同问题,即它必须在每个编译单元中都可以访问。

所以我接受了对目标类的轻微修改。我的想法是在目标类中“注入”监视类的析构函数,并带有“虚拟”(可能是多个)继承。当然,目标类可能是另一个的一个孩子,所以它看起来像是虚拟继承的工作。这是我到目前为止提出的。

我有两个问题。

这是对虚拟继承的一种很好的用法吗?与这个 parashift 建议anysubsubclass相反,使用 virtual 关键字(参见定义,它没有派生类)离开继承树中的最后一片叶子是否正确?关键是我想尽可能少地打扰我是否要在未来添加或删除,例如,在基类和最后一个派生类之间。anysubsubclassanysubclass

第二。正如您在我的代码中看到的,如果其中一个目标类具有 或 的重载operator=,或者具有复制构造函数,则永远不会调用operator=或 的复制构造函数track_death,这是一个问题,因为track_death包含无法复制的字段使用其简单的复制构造函数。我的解决方案是告诉实现者any*class他必须调用copy_info()被复制的对象,这看起来很容易出错。有更好的解决方案吗?

0 投票
3 回答
153 浏览

c++ - 虚拟继承

如果我有类似的东西

然后构造 Derived 对象的构造函数调用顺序是

即按照它们出现的顺序

但是,如果我将其更改为派生类: public Base1, virtual public Base2 {}; 然后构造函数调用的顺序变为

我不明白为什么会这样?

另一个简单的疑问:虚拟继承Base1的意义和目的是什么。

0 投票
4 回答
7258 浏览

c++ - C ++中接口的多重继承中的歧义

我做了一个测试代码如下:

我写这段代码的原因是为了测试函数 funcBase() 是否可以在 DDerived 的实例中调用。当我尝试编译此代码时,我的 C++ 编译器 (Visual Studio 2010) 给了我一条编译错误消息。在我看来,这段代码没有问题,因为它肯定funcBase()会在接口的某个派生类中实现(因此被覆盖)DDerived,因为它是纯虚拟的。换句话说,任何类型的指针变量都Implementation *应该与派生实现并覆盖函数的类的实例相关联funcBase()

我的问题是,为什么编译器会给我这样的错误信息?为什么 C++ 语法是这样定义的;即,将这种情况视为错误?如何使代码运行?我想允许接口的多重继承。当然,如果我使用“虚拟公共”或重新声明funcBase()Implementation功能

然后一切运行没有问题。

但是我不想那样做,寻找更方便的方法,因为虚拟继承可能会降低性能,如果类的继承关系非常复杂,重新声明会很繁琐。除了使用虚拟继承之外,还有其他方法可以在 C++ 中启用接口的多重继承吗?