我有以下情况:
class A
{
public:
A(std::string id);
};
class B : public virtual A
{
public:
B();
};
class C : public virtual A
{
public:
C();
};
class D : public B, public C
{
public:
D(std::string id);
};
D::D(std::string id) : A(id), B(), C()
{
}
class X : public D
{
public:
X(std::string id);
}
X::X(std::string id) : D(id)
{
}
现在,如果我创建一个D的实例,一切正常。但是,如果我创建一个X实例,我会得到一个编译器错误,告诉我某些东西试图调用A的默认构造函数 - 它不存在。如果我创建它,它会编译,但只调用默认构造函数,因此,id未正确设置/初始化。
这可以通过实现X的构造函数来解决:
X::X(std::string id) : A(id), D(id)
{
}
但我的理解是,这应该是不必要的。那么我的错误在哪里?
答案 0 :(得分:1)
您需要创建所有构造函数public
并为A
定义默认构造函数,因为字符串构造函数会将默认构造函数标记为=delete
。此外,the most derived class will initialize any virtual base class引用draft Standard:
12.6.2初始化基础和成员[class.base.init]
10在非委托构造函数中,初始化继续进行 以下顺序: - 首先,仅适用于最多的构造函数 派生类(1.8),虚拟基类按顺序初始化 它们出现在一个深度 - 从左到右遍历的定向 基类的非循环图,其中“从左到右”是基数的顺序 派生类中基类的外观 基SPECI音响ER-列表。
在这种情况下,这意味着X
必须确实初始化A
。
#include <iostream>
#include <string>
class A
{
public:
A() { std::cout << "A\n"; }
A(std::string id) { std::cout << id << " A(id)\n"; }
};
class B : public virtual A
{
public:
B() { std::cout << "B\n"; }
};
class C : public virtual A
{
public:
C() { std::cout << "C\n"; }
};
class D : public B, public C
{
public:
D(std::string id): A(id) { std::cout << id << " D(id)\n"; }
};
class X : public D
{
public:
X(std::string id): A(id), D(id) { std::cout << id << " X(id)\n"; }
};
int main()
{
X x("bla");
x;
}