Как использовать параметризованный конструктор базового класса после виртуального наследования

У меня есть структура класса, которая выглядит следующим образом:

  O
  |
  A
 / \
B   C
 \ /
  D
  |
  E

И конструкторы работают следующим образом (конкретный код не включен для краткости, но я могу конкретизировать его, если это необходимо):

class O {
  protected:
    O(const string &str) {
      //Does stuff with str
    };
}

class A : public O {
  protected:
    A(const string &str) : O(str) { };
}

class B : public virtual A {
  protected:
    B(const string &str) : A(str) { };
}

class C : public virtual A {
  protected:
    C(const string &str) : A(str) { };
}

class D : public B, public C {
  protected:
    D(const string &str) : B(str), C(str) { };
}

class E : public D {
  public:
    E(const string &str) : D(str) { };
}

Предполагается, что классы O, A, B, C и D являются частью библиотеки, а класс D является базовым классом для любых классов, которые я создам позже (например, E). Единственная цель D — упростить наследование для таких классов, как E. Моя проблема в том, что конструктор E вызывает конструктор по умолчанию для A, если я явно не вызываю параметризованный конструктор A, что противоречит цели D.

Эта структура наследования лучше всего подходит для моего приложения, поскольку классы C и D используются для специализации инфраструктуры, созданной A и B. C содержит дополнительные методы для A.

Есть ли способ заставить D обрабатывать вызов параметризованного конструктора A? В идеале я хотел бы, чтобы инициализация E вызывала конструкторы A, B, C, D, E в указанном порядке. Строковый параметр очень важен для классов выше по течению от O, а конструкторы B и C должны запускать определенные функции.


person dkt01    schedule 11.01.2016    source источник
comment
Нужен ли A конструктор по умолчанию?   -  person aschepler    schedule 12.01.2016
comment
Эта классовая структура никогда не бывает хорошей вещью.   -  person erip    schedule 12.01.2016
comment
@aschepler - A не нуждается в конструкторе по умолчанию, за исключением возможности построения E без явного вызова строкового конструктора A.   -  person dkt01    schedule 12.01.2016
comment
@erip - я согласен, что это не идеально, но, учитывая более широкую структуру классов, охватывающую этот раздел, это был самый простой макет без создания повторяющихся классов.   -  person dkt01    schedule 12.01.2016


Ответы (1)


Нет. Виртуальные базовые классы всегда должны создаваться наиболее производным классом. Это не может работать по-другому. Все, что вы можете сделать, это не разрешать A быть конструируемым по умолчанию и попросить компилятор помочь вам, или реорганизовать свой код, чтобы в первую очередь не использовать алмазное наследование.

person Puppy    schedule 11.01.2016
comment
Не тот ответ, которого я действительно хотел, но то, что я ожидал. Спасибо! - person dkt01; 12.01.2016