Каковы правила создания поэтапного конструктора?
Я обнаружил, что возможность использования синтаксиса списка инициализаторов для класса зависит от того, имеют ли поля класса значения по умолчанию. Почему?
Чтобы быть точным, рассмотрим следующий код:
class S
{
public:
int a;
};
...
int a;
S s{ a };
Он компилируется без каких-либо проблем. Но если я добавлю значение по умолчанию в поле класса, он перестанет строить:
class S
{
public:
int a = 0;
};
...
int a;
S s{ a };
Ошибка 1 ошибка C2440: 'initializing': не может преобразовать из 'initializer-list' в 'S'
Почему? Что еще влияет на создание такого конструктора?
Ответы
Ответ 1
В С++ 14 ваш код действителен и должен компилироваться с любым совместимым с С++ 14 компилятором.
В С++ 11:
Если у вас нет значения по умолчанию для a
, ваш тип является агрегатом, и таким образом агрегатная инициализация может быть выполнена:
Агрегат является одним из следующих типов:
Как только вы добавите значение по умолчанию для атрибута a
, ваша агрегатная инициализация больше не будет выполняться, так как ваш тип перестает быть агрегатом.
Ответ 2
Показанный код компилируется без каких-либо проблем с gcc 6.1.1. Вероятно, вы используете старый компилятор, который не поддерживает полностью С++ 14:
$ cat t.C
class S
{
public:
int a = 0;
};
void foo()
{
int a=4;
S s{a};
}
$ g++ -std=c++1z -g -c -o t.o t.C
$ g++ --version
g++ (GCC) 6.1.1 20160510 (Red Hat 6.1.1-2)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Ответ 3
В обоих случаях конструктор по умолчанию S
не принимает аргументов. Форма класса не влияет на генерацию конструктора по умолчанию. Кроме того, нет неявно сгенерированного конструктора, принимающего int
.
Если S
является агрегатом, то использование S s = { arguments_opt };
не вызывает конструктор S
. Вместо этого он вызывает что-то, называемое агрегатной инициализацией. Агрегаты - это единственные классы, которые могут быть созданы объектами этого класса без вызова конструктора.
Только если S
является не агрегатом, то S s = { arguments_opt };
пытается сопоставить список аргументов с параметрами конструктора S
.
(Как объяснялось другими, в С++ 11, предоставление элемента для выравнивания или выравнивания для нестатического элемента данных делает класс не агрегатом).