У меня есть следующий сценарий:
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 по умолчанию — который не существует. Если я его создаю, он компилируется, но вызывается только конструктор по умолчанию, и, соответственно, идентификатор не установлен / инициализирован неправильно.
Это можно исправить, реализовав конструктор X следующим образом:
X::X(std::string id) : A(id), D(id)
{
}
Но я понимаю, что это не нужно. Так где моя ошибка?
Вам нужно сделать все ваши конструкторы 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;
}
Других решений пока нет …