构造函数继承的虚拟继承
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) ;
有没有办法将构造函数继承与我忽略的虚拟继承结合起来? 如果没有,您会使用什么替代方案? 也许可变参数模板构造函数可以完美地将其参数转发到所有基础?
【问题讨论】:
InPort
和 OutPort
都继承了一个构造函数,该构造函数为 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++ 错误,不是吗?以上是关于构造函数继承的虚拟继承的主要内容,如果未能解决你的问题,请参考以下文章