Ответ 1
Это новая функция, добавленная в С++ 17. То, что происходит, - это C
, теперь считается совокупностью. Поскольку это агрегат, ему не нужен конструктор. Если мы посмотрим на [dcl.init.aggr]/1, то получим, что агрегат
Агрегат - это массив или класс с
нет пользовательских, явных или унаследованных конструкторов ([class.ctor]),
нет частных или защищенных нестатических членов данных (пункт [class.access]),
нет виртуальных функций, и
нет виртуальных, частных или защищенных базовых классов ([class.mi]).
[Примечание: Агрегированная инициализация не позволяет получить доступ к защищенным и закрытым членам или конструкторам базового класса. - конец примечания]
И мы проверяем все эти пункты пули. У вас нет конструкторов, объявленных в C
или D
поэтому есть пункт 1. У вас нет элементов данных, поэтому второй пункт не имеет значения, а ваш базовый класс общедоступен, поэтому третий пункт удовлетворен.
Изменения, произошедшие между С++ 11/14 и С++ 17, которые позволяют это, состоят в том, что агрегаты теперь могут иметь базовые классы. Вы можете увидеть старую формулировку здесь, где прямо указано, что базовые классы не допускаются.
Мы можем подтвердить это, проверив черту std::is_aggregate_v
как
int main()
{
std::cout << std::is_aggregate_v<C>;
}
который напечатает 1.
Обратите внимание, что, поскольку C
является другом B
вы можете использовать
C c{};
C c1;
C c2 = C();
Как действительные способы инициализации C
Поскольку D
не друг B
единственный, кто работает, это D d{};
как это совокупная инициализация. Все другие формы пытаются инициализировать по умолчанию, и это не может быть сделано, так как D
имеет удаленный конструктор по умолчанию.