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并调用它。为什么会这样?
答案 0 :(得分:2)
关于虚拟继承的要理解是,当你真正从一个类继承时,它会转到" front"继承"队列&#34 ;;也就是说,您必须在所有其他基类之前初始化虚拟基础。
在这种情况下,ConcreteDerived
通过Base
将VirtualDerived
作为间接虚拟基础。由于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 ++让你在最派生的类中选择。