Наследяване на конструктор и предоставяне на ново претоварване: базовият конструктор без аргументи изглежда не участва в разрешаването на претоварването

Тестовете показват странно поведение (c++14, g++ 4.9.1, clang 3.5.5):

Накратко:

  • ако B не предоставя други конструктори, може да използва A::A()
  • ако B предоставя други конструктори, той не може да използва A::A(), но използва A::A(whatever arguments), което е неочаквано поведение (поне за мен).

Настройка 1:

struct A {
  A() {};
  A(int) {}; // with or without this overload the result are the same
};

struct B : A {
  using A::A;
};

B b0{}; // OK

Настройка 2:

struct A {
  A() {}; // with a default constructor instead (empty class A)
          // the results are the same
};

struct B : A {
  using A::A;
  B(int){}
};

B b0{}; // no matching constructor
B b1{24}; // OK

Настройка 3:

struct A {
  A() {};
  A(int) {};
};

struct B : A {
  using A::A;
  B(int, int){}
};

B b0{}; // no matching constructor
B b1{24}; // OK
B b2{24, 42}; // OK

Защо се случва това и как може да се "поправи".


person bolov    schedule 24.02.2015    source източник
comment
Конструкторът по подразбиране е специален. Можете да го поправите напр. чрез писане на изрично деклариране на конструктора по подразбиране и по подразбиране: B() = default; Предполагам, че някои свойства на конструктора по подразбиране не могат да бъдат възпроизведени от наследяващ конструктор, като тривиалност, оттук и специалните правила.   -  person dyp    schedule 24.02.2015
comment
Това ли са точните примери, с които строите, те не работят или аз? Можете ли да предоставите връзка на живо? т.е. wandbox или Coliru   -  person Shafik Yaghmour    schedule 24.02.2015
comment
@dyp Прав си. Защо не включите коментара си в отговор? ;)   -  person Daniel Frey    schedule 24.02.2015
comment
Примерите не трябва да са реални. От една страна, вие не наследявате нищо. Моля, създайте MCVE.   -  person    schedule 24.02.2015
comment
сори, написах вместо да копирам, оправих наследяването.   -  person bolov    schedule 24.02.2015
comment
@DanielFrey, защото не съм напълно сигурен в обосновката. Препрочитайки предложението, изглежда има някакво нетривиално взаимодействие между правилата за наследяване на ctors и имплицитното генериране на ctors. Това също може да е причината за изключенията (без ctor по подразбиране, копиране, преместване чрез наследяване на ctor).   -  person dyp    schedule 24.02.2015
comment
Вместо резултатът да е същият, моля, посочете в тестовия случай какво се случва, което не искате да се случи (или обратното). Вашият въпрос е труден за разбор.   -  person Lightness Races in Orbit    schedule 24.02.2015
comment
@DanielFrey Също така, дубликати. stackoverflow.com/q/20435859 и др.   -  person dyp    schedule 24.02.2015
comment
bolov, писането е добро (все пак ще трябва да поправите форматирането), но след това копирайте обратно и проверете кода си.   -  person Yakk - Adam Nevraumont    schedule 24.02.2015
comment
@LightnessRacesinOrbit Частта в OP как може да бъде коригирана вероятно го прави отделен въпрос, нали? (Поне можете да добавите това към отговора си :) ) -- редактиране: опа, направихте това. също: xkcd.com/541   -  person dyp    schedule 24.02.2015


Отговори (1)


Не мога да ви кажа обосновката за това, но мога поне да ви кажа, че е стандартно задължено:

[C++11: 12.9/3]: За всеки нешаблонен конструктор в кандидат-набора от наследени конструктори различен от конструктор без параметри или конструктор за копиране/преместване с един параметър, конструкторът имплицитно се декларира със същите характеристики на конструктора освен ако няма деклариран от потребителя конструктор със същия подпис в класа, където се появява using-declaration. [..]

Тъй като B() по подразбиране извиква A() по подразбиране, можете да го "поправите" по следния начин:

struct B : A
{
   B() = default;

   using A::A;
   B(int, int){}
};

(демонстрация на живо)

Следната формулировка от оригиналното предложение (n2540) предполага, че лекотата и симетрията на тази корекция е повече или по-малко водещият фактор зад решението, въпреки че все още намирам това за малко незадоволително. О, добре.

Конструкторите за копиране и конструкторите по подразбиране не се препращат, като се отчитат съществуващите правила за имплицитно деклариране на конструктори за копиране/по подразбиране.

person Lightness Races in Orbit    schedule 24.02.2015