C++ делегирование ctor и родительского ctor с аргументом

Это не похоже на работу в C++11:

class B : public A
{
  public:
    B(const A& a)
        : A(a)   // parent constructor for passing the parameter
        , B()    // delegating constructor for init of other members
    {};
  // ...
};

GCC говорит мне, что an initializer for a delegating constructor must appear alone,

Как мне вызвать конструктор родительского класса с параметром и вызвать базовый конструктор класса B? (У меня есть куча других конструкторов в B, которые нуждаются в таком же поведении).

Прямо сейчас я рассматриваю возможность написания частного B::init() функционировать и использовать его во всех телах конструктора, но это немного похоже на C++03.

Какое решение является предпочтительным?

2 ответа

Решение

Я полагаю, что предпочтительный способ делегирования заключается в обратном: он предназначен не для рефакторинга общих частей конструкторов, а для определения более простого варианта как особого случая более сложного случая.

Итак, вы должны начать с B(const A& a) и использовать это как цель делегирования.

class B : public A
{
  public:
    B() : B(A());
    B(const A& a) : A(a)   // parent constructor for passing the parameter
    {};
};

Ты звонишь A() в любом случае при создании B,

Логическое обоснование этого заключается в том, что когда у вас есть два "частично специализированных" c'tors, вы не сможете использовать их для инициализации сложного. Например:

class B : public A
{
  public:
    B() {};
    B(int) : B() {};
    B(double) : B() {};
    B(double,int) : B(int), B(double) {}; // can't do it.
};

Я полагаю, что техническая причина объясняется в ответе Вирсавии. Посмотрите, что случилось бы, если бы у вас была общая роль в B():

class B : public A
{
  public:
    B() {};
    B(int) : B() {};
    B(double) : B() {};
    B(double,int) : B(int), B(double) {}; //ooops would get B() called twice!
};

Это проблема алмазов, известная по наследству. Решение состоит в том, чтобы изменить логику.

class B : public A
{
  public:
    B() : B(0,0) {};
    B(int a) : B(a,0) {};
    B(double d) : B(0,d) {};
    B(double a, int d) {/*full implementation*/};
};

B(const A& a) : A(a), B() не имеет смысла, так как B() также инициализирует базовый класс A, По сути, это будет дублирующая инициализация, которая является внутренним противоречием.

Единственный реальный вариант для языка - запретить что-либо еще, если вы используете делегированный конструктор. Это то, что говорит вам ваш компилятор.

Другие вопросы по тегам