2015-04-15 128 views
13

虚拟继承我有一个类层次结构,其归结为与构造继承

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); 

即使is not enough一个更明确的版本替换的InOutPort定义:

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) { } }; 

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

+0

'InPort'和'OutPort'都继承了一个构造函数,它调用'Port'的未声明的默认构造函数,因为它们都不是派生类最多的类。如果这个程序被调用,该程序将是不合格的。因此,gcc决定删除这两个类中相应的构造函数。即使基地[明确初始化](http://coliru.stacked-crooked.com/a/7c2963ba56e79793),Clang也不会给出有关构造函数的错误。另外,clang也会给出一个错误,因为在using声明中'Port'不是'InOutPort'的直接基类,而gcc忽略它。 – 0x499602D2

+0

GCC实际上删除了构造函数,因为它们会形成不规则的,但不是因为我之前推测的原因。看来使用声明[隐式地使用默认构造函数](http://coliru.stacked-crooked.com/a/490c0b5bb17fdc50)。 “Port”类中的默认构造函数未声明,因此它将删除调用构造函数。这是一个错误。 – 0x499602D2

+0

另外,它只会发生在它是虚拟基类的情况下。 – 0x499602D2

回答

1

似乎没有办法做这样的事情。在12.9/8:

...一个隐式定义的继承构造执行集的类的 初始化将由用户编写 直列构造为类执行的MEM-initializer-列表,其 只有MEM-初始化有MEM-初始化-ID如下规定名称的基础 类在using声明 和表达式列表的嵌套名称符记...

换句话说,您继承的构造函数的类是只有获取转发给它的参数的基类。所有其他基类都需要具有默认构造函数。由于您通过继承父构造函数将这些默认构造函数隐藏在中间类中,因此一旦明确继承父构造函数后就不能调用它们。

我认为你应该可以为两个中间类使用继承的构造函数,并且只为大部分派生类编写显式版本[我没有看到你已经试过这个 - 它看起来像是我的编译器错误对标准的理解]。如果我想到另一种更好的方法,我会更新。

+0

这几乎是我将我的大脑扭回到虚拟继承过程中的想法 - 但为什么中间版本(显式的'InOutPort'继承'InPort'和'OutPort')不起作用?这似乎是一个g ++的bug,不是吗? –