3

我有以下情况:

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

但我的理解是,这应该是不必要的。那么我的错误在哪里?

4

1 回答 1

2

您需要创建所有构造函数public并定义一个默认构造函数,A因为字符串构造函数会将默认构造函数标记为=delete. 此外,最派生的类将初始化任何虚拟基类,引用标准草案

12.6.2 初始化基和成员 [class.base.init]

10 在非委托构造函数中,初始化按以下顺序进行: — 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们出现在深度优先的顺序进行初始化。 - 基类的有向无环图的右遍历,其中“从左到右”是派生类基类说明符列表中基类的出现顺序。

在这种情况下,这意味着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;       
}
于 2013-01-29T13:18:03.910 回答