具有抽象中间类的虚拟继承

Posted

技术标签:

【中文标题】具有抽象中间类的虚拟继承【英文标题】:Virtual inheritance with abstract middle class 【发布时间】:2014-11-05 05:44:04 【问题描述】:

这不是关于如何做某事的问题,我对虚拟继承了如指掌,并且我知道一些规避这个问题的方法 - 但没有一个是我满意的。

这是一些无法编译的代码:

struct BottomClass

    BottomClass(int& ref) : ref(ref) 
    int& ref;
;

struct MiddleClassA : virtual public BottomClass

    MiddleClassA() /*: BottomClass()*/ 
    virtual ~MiddleClassA() = 0;
;

MiddleClassA::~MiddleClassA()

struct MiddleClassB : virtual public BottomClass

    MiddleClassB() /*: BottomClass()*/ 
    virtual ~MiddleClassB() = 0;
;

MiddleClassB::~MiddleClassB()

struct TopClass final : public MiddleClassA, public MiddleClassB

    TopClass(int& ref) : BottomClass(ref) 
;

void main()

    int someInt;
    TopClass variable(someInt);

困扰我的是为什么它不能编译。我知道 BottomClass 没有默认构造函数,因此 MiddleClassX 格式不正确。但是 MiddleClassX 是抽象类!即使我在那里指定了一个构造函数,它在任何情况下都不会被使用......那我为什么要指定呢?

我什至不能在那里给出一个合理的构造函数,因为 MiddleClassX 没有任何合理的值可以赋予 BottomClass。

我的问题是:这个问题有没有优雅的解决方案?


我自己有一些解决方案,但我不喜欢其中任何一个:

1) 我可以创建一个 BottomClass 默认构造函数,它使用一些垃圾值来构造它的 ref。然后 assert() 在那个构造函数中,所以我知道它永远不会被调用......当然这导致我不得不对所有应该是编译时错误的东西进行运行时检查,而且它实际上也需要存在获取引用的垃圾整数。

2)我可以将引用传递给每个抽象的中产阶级并使用它......但这会导致信息的严重重复,并且当这些链变长时(就像它们那样),维护它是非常乏味的。必须向每个类传递一个额外的变量也会对性能造成影响。

(如果我的问题难以理解,我深表歉意 - 如果有人能更好地描述我的困境,那就太棒了,我很难用语言表达)

【问题讨论】:

【参考方案1】:

即使我在那里指定了一个构造函数,它在任何情况下都不会被使用

错了。派生类使用抽象类的构造函数。抽象类毕竟还是需要初始化的,抽象类唯一的特别之处就是你不能直接构造它们;只有派生类可以构造它们,并且只能作为它们自己构造的一部分。

没有构造函数的抽象类不能被派生,就像任何其他没有构造函数的类不能被派生一样。

您的第二个解决方案是正确的。如果链上的构造函数是内联的,那么根本不会影响性能。

(顺便说一句,这与虚拟继承毫无关系。非虚拟继承也会遇到同样的问题。)

【讨论】:

好吧,我的意思是:用 MiddleClassX() 替换构造函数:BottomClass(((std::cout 也许您不记得虚拟继承和非虚拟继承之间的区别?虚拟继承的基类需要从派生类链中的每个类的*显式构造...我的问题是因为我需要在无论如何都将被强制覆盖的地方指定构造函数。 对不起,我几乎肯定这只适用于虚拟继承。只是,如果您认为不是,那么我可能误解了我的问题...【参考方案2】:

为什么不声明一个默认构造函数...

BottomClass();  // deliberately undefined; use Bottom(int&)

...并保持未定义 - 如果实际尝试使用它,最坏的情况是会出现链接时错误。

见ideone.com

【讨论】:

这对我来说无法编译(Visual Studio 2013)。如果真的发生了,那就太棒了!但是...实际上它在 ideone 上运行让我有点惊讶,实际上... @Ace24713 可能会尝试以template <class T> 为前缀然后... 仅在实际调用时才应实例化...。 其实我早就想到了,但没有运气。它仍然试图链接到它。如果有任何证据表明该代码应该按照 c++ 标准编译,我会写一个错误报告并完成它? 最后一个想法:尝试制作 MiddleClassX 构造函数模板。重新标准 - 不是那种我可以发誓的事情,所以我会让你检查那一边,因为我很忙;-P。 还是没有运气。 (但老实说,即使这样有效,我也会倾向于称其为 VS 错误)谢谢!

以上是关于具有抽象中间类的虚拟继承的主要内容,如果未能解决你的问题,请参考以下文章

通过 void 指针通过 C ABI 传递 C++ 对象(可能具有多重虚拟继承)

详细的解释下类的封装性,抽象性,继承性和多态性。

如何检测和断言特定类的虚拟继承?

如何防止具有公共派生类的抽象类在其他程序集中被继承?

虚拟继承中派生类的大小

获取从抽象类继承并在属性中具有特定值的类的实例