构造函数继承的虚拟继承

Posted

技术标签:

【中文标题】构造函数继承的虚拟继承【英文标题】:Virtual Inheritance with Constructor Inheritance 【发布时间】:2015-06-21 14:41:31 【问题描述】:

我有一个类层次结构,可以归结为

class Module  ;

struct Port 
    Module& owner;
    Port(Module& owner) : owner(owner) 
;

struct InPort    : virtual Port     using Port::Port; ;
struct OutPort   : virtual Port     using Port::Port; ;
struct InOutPort : InPort, OutPort  using Port::Port; ;

如您所见,我更愿意创建一些基本功能,并以经典的菱形图案继承它。我还想使用构造函数继承来使其成为未来的证据......

但是,this does not work as written down above

prog.cpp: In function 'int main()':
prog.cpp:14:15: error: use of deleted function 'InOutPort::InOutPort(Module&)'
  InOutPort p(m);

甚至将InOutPort 的定义替换为更明确的版本is not enough:

struct InOutPort : InPort, OutPort  InOutPort(Module& m) : Port(m), InPort(m), OutPort(m)   ;

改为I seem to have to write down everything explicitly for it to work::

struct InPort    : virtual Port     InPort(Module& m) : Port(m)   ;
struct OutPort   : virtual Port     OutPort(Module& m) : Port(m)   ;
struct InOutPort : InPort, OutPort  InOutPort(Module& m) : Port(m), InPort(m), OutPort(m)   ;

有没有办法将构造函数继承与我忽略的虚拟继承结合起来? 如果没有,您会使用什么替代方案? 也许可变参数模板构造函数可以完美地将其参数转发到所有基础?

【问题讨论】:

InPortOutPort 都继承了一个构造函数,该构造函数为 Port 调用未声明的默认构造函数,因为它们都不是派生最多的类。如果调用它们,该程序将是格式错误的。正因为如此,gcc 决定删除两个类中相应的构造函数。即使基数是initialized explicitly,Clang 也不会给出关于构造函数的错误。顺便说一句,clang 也给出了一个错误,因为 Port 在 using 声明中不是 InOutPort 的直接基类,而 gcc 会忽略它。 GCC 实际上确实删除了构造函数,因为它们的格式不正确,但不是因为我之前推测的原因。似乎使用声明implicitly odr-uses the default-constructor。 Port 类中的默认构造函数未声明,因此它删除了调用构造函数。这是一个错误。 另外,只有当它是一个虚拟基类时才会发生。 【参考方案1】:

似乎没有任何方法可以做这样的事情。在 12.9/8 中:

...隐式定义的继承构造函数执行一组 将由用户编写的类的初始化 具有 mem-initializer-list 的该类的内联构造函数,其 只有 mem-initializer 具有命名基础的 mem-initializer-id 在使用声明的嵌套名称说明符中表示的类 以及如下指定的表达式列表...

换句话说,您继承其构造函数的类是唯一 将参数转发给它的基类。所有其他基类都需要具有默认构造函数。由于你通过继承父构造函数将这些默认构造函数隐藏在中间类中,因此一旦显式继承父构造函数就无法调用它们。

我认为您应该能够为两个中间类使用继承的构造函数,并且只为最派生的类编写显式版本的标准]。如果我想到另一种更好的方法,我会更新。

【讨论】:

这几乎就是我在将我的大脑转回虚拟继承过程后得出的结论 - 但为什么中间版本(显式 InOutPort 继承 InPort 和 `OutPort´)不起作用?这似乎是一个 g++ 错误,不是吗?

以上是关于构造函数继承的虚拟继承的主要内容,如果未能解决你的问题,请参考以下文章

虚拟继承 - 跳过构造函数

使用虚拟继承和委托构造函数在构造函数中崩溃

使用虚拟继承时调用默认构造函数[重复]

在使用 C++ 进行虚拟继承期间调用构造函数

C++继承详解

C++继承详解