无法从具有虚拟继承的类派生(C ++虚拟继承)

时间:2015-12-01 00:36:17

标签: c++ inheritance constructor initialization virtual-inheritance

class Base
{
public:
    Base(std::string arg1, std::string arg2) : arg1(arg1), arg2(arg2) {}
    string arg1,arg2;
    virtual void f() = 0;
    inline virtual ~Base() {}
};

class Mixin1 : virtual public Base
{
};

//Virtual class uses virtual base and a mixin
class VirtualDerived : virtual public Base, public Mixin1
{
public:
    VirtualDerived(string arg2) : Base("some literal", arg2) {}
};

//Here I am concretely subclassing VirtualDerived, whose constructor constructs all virtual superclasses.
class ConcreteDerived : public VirtualDerived
{
public:
    ConcreteDerived(string arg2) : VirtualDerived(arg2) {}
    inline void f() {}
};

int main(int argc, const char * argv[]) {

    ConcreteDerived cd("hello");

    return 0;
}

我从VirtualDerived派生,其构造函数将初始化Base。我是否明确声明VirtualDerived对Mixin1虚拟的继承没有任何区别。

我得到的错误是ConcreteDerived必须显式调用Base的构造函数。

使ConcreteDerived的继承虚拟同样没有区别。

问题不在于VirutalDerived的构造函数转发。如果我实现f使其成为一个概念类,我可以毫无问题地创建它:

class VirtualDerived : virtual public Base, public Mixin1
{
public:
    VirtualDerived(string arg2) : Base("some literal", arg2) {}
    inline void f(){}
};

int main(int argc, const char * argv[]) {

    VirtualDerived cd("hello");

    return 0;
}

编译器似乎明白,当直接创建VirtualDerived时,VirtualDerived的构造函数会调用Base的非平凡构造函数。但是,如果某些东西派生出VirtualDerived并调用它。为什么会这样?

1 个答案:

答案 0 :(得分:2)

关于虚拟继承的要理解是,当你真正从一个类继承时,它会转到" front"继承"队列&#34 ;;也就是说,您必须在所有其他基类之前初始化虚拟基础。

在这种情况下,ConcreteDerived通过BaseVirtualDerived作为间接虚拟基础。由于Base没有默认构造函数,因此您必须在ConcreteDerived的初始化列表中指定它。

理由是这样的:假设你有另一个中级类,比如

class VirtualDerived2 : virtual public Base
{
public:
    VirtualDerived2() : Base("arg1", "arg2") {}    
};

此处VirtualDerived2也几乎从Base继承,并使用自己的参数集对其进行初始化。现在我们添加另一个具体的类:

class ConcreteDerived2 : public VirtualDerived, public VirtualDerived2
{
    // ...
};

现在ConcreteDerived2有两个基类,它们实际上都是从Base继承的。但是,层次结构中只有Base的一个副本 - 这是整个虚拟继承点。那么现在您将使用哪些参数来初始化Base的(单个)副本?那些来自VirtualDerived或来自VirtualDerived2的人?对此没有好的答案,所以C ++让你在最派生的类中选择。