无法从具有虚拟继承的 class 派生(C++ 虚拟继承)
Cannot derive from class with virtual inheritance (C++ 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 virtual 的继承与否没有区别。
我得到的错误是 ConcreteDerived 必须显式调用 Base 的构造函数。
使 ConcreteDerived 的继承虚拟化同样没有区别。
问题不在于 VirutalDerived 的构造函数转发。如果我实现 f 使其成为一个具体的 class,我可以毫无问题地创建它:
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 并调用它,则不会。为什么会这样?
关于虚继承要理解的一点是,当你从一个class虚继承时,它会转到继承"queue"的"front";也就是说,您必须在所有其他基础 classes.
之前初始化虚拟基础
在这种情况下,ConcreteDerived
通过 VirtualDerived
将 Base
作为间接虚拟基础。由于 Base
没有默认构造函数,您必须在 ConcreteDerived
.
的初始化列表中指定它
推理是这样的:假设你有另一个中间体 class 例如
class VirtualDerived2 : virtual public Base
{
public:
VirtualDerived2() : Base("arg1", "arg2") {}
};
这里VirtualDerived2
实际上也继承自Base
,并用自己的一组参数初始化它。现在我们添加另一个具体的 class:
class ConcreteDerived2 : public VirtualDerived, public VirtualDerived2
{
// ...
};
现在 ConcreteDerived2
有两个基础 class,它们实际上都继承自 Base
。但是您在层次结构中只有 Base
的一个副本——这就是虚拟继承的全部要点。那么现在您要使用哪些参数来初始化 Base
的(单个)副本?来自 VirtualDerived
的那些,还是来自 VirtualDerived2
的那些?这个没有好的答案,所以C++让你选择最派生的class.
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 virtual 的继承与否没有区别。
我得到的错误是 ConcreteDerived 必须显式调用 Base 的构造函数。
使 ConcreteDerived 的继承虚拟化同样没有区别。
问题不在于 VirutalDerived 的构造函数转发。如果我实现 f 使其成为一个具体的 class,我可以毫无问题地创建它:
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 并调用它,则不会。为什么会这样?
关于虚继承要理解的一点是,当你从一个class虚继承时,它会转到继承"queue"的"front";也就是说,您必须在所有其他基础 classes.
之前初始化虚拟基础在这种情况下,ConcreteDerived
通过 VirtualDerived
将 Base
作为间接虚拟基础。由于 Base
没有默认构造函数,您必须在 ConcreteDerived
.
推理是这样的:假设你有另一个中间体 class 例如
class VirtualDerived2 : virtual public Base
{
public:
VirtualDerived2() : Base("arg1", "arg2") {}
};
这里VirtualDerived2
实际上也继承自Base
,并用自己的一组参数初始化它。现在我们添加另一个具体的 class:
class ConcreteDerived2 : public VirtualDerived, public VirtualDerived2
{
// ...
};
现在 ConcreteDerived2
有两个基础 class,它们实际上都继承自 Base
。但是您在层次结构中只有 Base
的一个副本——这就是虚拟继承的全部要点。那么现在您要使用哪些参数来初始化 Base
的(单个)副本?来自 VirtualDerived
的那些,还是来自 VirtualDerived2
的那些?这个没有好的答案,所以C++让你选择最派生的class.