В C ++ 14 определение совокупности было:
Агрегат - это массив или класс (Clause [class]) без предоставленных пользователем конструкторов ([class.ctor]), без закрытых или защищенных нестатических элементов данных (Clause [class.access]), без базовых классов (пункт [class.derived]) и без виртуальных функций ([class.virtual]).
Следовательно, B
не является совокупностью. В результате B{}
, безусловно, не является агрегатной инициализацией, а B{}
и B()
означают одно и то же. Они оба просто вызывают конструктор B
по умолчанию.
Однако в C ++ 17 определение совокупности было изменено на:
агрегат - это массив или класс с
- нет пользовательских, явных или унаследованных конструкторов ([class.ctor]),
- нет личных или защищенных нестатических элементов данных (пункт [class.access]),
- без виртуальных функций и
- нет виртуальных, частных или защищенных базовых классов ([class.mi]).
[Примечание: Совокупная инициализация не позволяет получить доступ к защищенным и закрытым членам или конструкторам базового класса. - конечная нота]
Ограничение больше не распространяется на любых базовых классов, а только на виртуальные / частные / защищенные. Но B
имеет публичный базовый класс. Теперь это совокупность! И агрегатная инициализация C ++ 17 позволяет инициализировать подобъекты базового класса.
В частности, B{}
- это агрегатная инициализация, в которой мы просто не предоставляем инициализатор для какого-либо подобъекта. Но первым (и единственным) подобъектом является A
, который мы пытаемся инициализировать с {}
(во время агрегатной инициализации любой подобъект без явного инициализатора инициализируется копией из {}
), который мы можем ' Это происходит потому, что конструктор A
защищен, а мы не друзья (см. также цитату).
<ч />
Обратите внимание, что для интереса в C ++ 20 определение совокупности *1059* снова изменится.