Почему я не могу скопировать инициализацию структуры, полученной из другой структуры?

Когда я запускаю этот код:

struct X { int a; }; struct Y : public X {}; X x = {0}; YY = {0}; 

Я получил:

 error: could not convert '{0}' from '' to 'Y' 

Почему инициализация скобок работает для базового classа, но не для производного classа?

Ваша проблема связана с агрегатной инициализацией : struct X является агрегатом, а struct Y – нет. Вот стандартная цитата об агрегатах (8.5.1):

Агрегат – это массив или class (раздел 9) без конструкторов, предоставляемых пользователем (12.1), без элементарных или равных инициализаторов для нестатических членов данных (9.2), без частных или защищенных нестатических элементов данных ( Раздел 11), нет базовых classов (раздел 10) и нет виртуальных функций (10.3).

В этом предложении указано, что если class имеет базовый class, то он не является совокупностью. Здесь struct Y имеет struct X в качестве базового classа и, следовательно, не может быть агрегатным типом.

Что касается конкретной проблемы, которую вы имеете, сделайте следующее предложение из стандарта:

Когда агрегат инициализируется списком инициализаторов, как указано в 8.5.4, элементы списка инициализаторов берутся как инициализаторы для членов агрегата, увеличивая индекс или порядок членов. Каждый член инициализируется копией из соответствующего предложения инициализатора. Если выражение initializer-выражение является выражением, и для преобразования выражения требуется суживающее преобразование (8.5.4), программа плохо сформирована.

Когда вы выполняете X x = {0} , инициализация агрегата используется для инициализации a до 0 . Однако, когда вы выполняете Y y = {0} , поскольку struct Y не является агрегированным типом, компилятор будет искать соответствующий конструктор. Поскольку ни один из неявно созданных конструкторов (по умолчанию, копирование и перемещение) не может ничего сделать с одним целым числом, компилятор отклоняет ваш код.


Что касается этого поиска конструкторов, сообщения об ошибках из clang ++ немного более ясны относительно того, что на самом деле пытается сделать компилятор ( онлайн-пример ):

 YY = {0}; ^ ~~~ main.cpp:5:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Y &' for 1st argument struct Y : public X {}; ^ main.cpp:5:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Y &&' for 1st argument struct Y : public X {}; ^ main.cpp:5:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided 

Обратите внимание, что есть предложение расширить агрегированную инициализацию для поддержки вашего варианта использования, и он превратился в C ++ 17. Если я прочитаю его правильно, это сделает ваш пример действительным с семантикой, которую вы ожидаете. Итак … вам остается только ждать компилятора, совместимого с C ++ 17.

  • Почему открытые поля быстрее, чем свойства?
  • Инициализация структуры языка программирования C / C ++?
  • Почему GCC не оптимизирует структуры?
  • Структурный конструктор в C ++?
  • как устанавливать и получать поля в структурах Golang?
  • Почему я не могу определить конструктор по умолчанию для структуры в .NET?
  • структурированная сериализация в C и передача через MPI
  • Почему 16 байтов рекомендуемый размер для структуры в C #?
  • Копирование структуры, содержащей указатели на устройство CUDA
  • Передача структуры в функцию
  • ARC запрещает объекты Objective-C в структурах или объединениях, несмотря на маркировку файла -fno-objc-arc
  • Давайте будем гением компьютера.