2016-04-05 4 views
2

Это не похоже на работу в C++ 11:C++ делегировании CTOR и родительский CTOR с аргументом

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 
    {}; 
    // ... 
}; 

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

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

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

Какое предпочтительное решение?

+1

Почему бы не написать в другом направлении? 'B :: B(): B (A {}) {}' и 'B :: B (const A & a): A (a), other_member {} {}'. – Jarod42

+0

@ Jarod42 Почему бы не написать ответ вместо комментария? – Barry

+1

@ Барри: Не уверен, если я что-то не пропущу. – Jarod42

ответ

5

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

Значит, вы должны начать с 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*/}; 
}; 
+0

Плюс один за предоставление решения, в отличие от моего ответа ;-) – Bathsheba

+1

Похож на плагиат комментария Барри = /. Но я начал писать его до его публикации. – luk32

+0

На мой взгляд, это не вред: комментарии - это бедный двоюродный брат ответа, поскольку первые не так легко рецензируются, и нет механизма принятия. – Bathsheba

2

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

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

+0

Абсолютно нет. – Bathsheba

+0

Извините, комментарий удален. – Gauthier

+0

Итак, это конфликт, потому что 'B()' вызывает 'A()', но затем я пытаюсь * также * вызывать 'A (a)', правильно? – Gauthier

Смежные вопросы