Каковы правила генерации полевого конструктора?

Я обнаружил, что возможность использования синтаксиса списка инициализаторов для класса зависит от того, имеют ли поля класса значения по умолчанию. Зачем?

Чтобы быть точным, рассмотрим следующий код:

class S
{
public:
int a;
};
...
int a;
S s{ a };

Компилируется без проблем. Но если я добавлю значение по умолчанию в поле класса, оно прекратит сборку:

class S
{
public:
int a = 0;
};
...
int a;
S s{ a };

Ошибка 1 ошибка C2440: «инициализация»: невозможно преобразовать из «списка инициализаторов» в «S»

Зачем? Что еще влияет на такую ​​генерацию конструктора?

16

Решение

В C ++ 14, Ваш код корректен и должен компилироваться любым C ++ 14-совместимым компилятором.


В C ++ 11 тем не мение:

Если у вас нет значения по умолчанию для aВаш тип является совокупным, и, таким образом, агрегатная инициализация можно выполнить:

Агрегат является одним из следующих типов:

  • тип массива

  • тип класса (как правило, структура или объединение), который имеет

    • нет частных или защищенных нестатических элементов данных
    • нет пользовательских конструкторов, в том числе унаследованных от общедоступных баз (начиная с C ++ 17) (допускаются явно заданные по умолчанию или удаленные конструкторы) (начиная с C ++ 11)
    • нет виртуальных, частных или защищенных (начиная с C ++ 17) базовых классов
    • нет виртуальных функций-членов
    • нет инициализаторов элементов по умолчанию (начиная с C ++ 11, до C ++ 14)

Как только вы добавите значение по умолчанию для атрибута aваша инициализация агрегата больше не может быть выполнена, поскольку ваш тип перестал быть агрегатом.

19

Другие решения

Показанный код компилируется без проблем с gcc 6.1.1. Скорее всего, вы используете старый компилятор, который не полностью поддерживает C ++ 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.
4

В обоих случаях конструктор по умолчанию S не принимает аргументов Форма класса не влияет на генерацию конструктора по умолчанию. Кроме того, не существует неявно сгенерированного конструктора, принимающего int,

Если S является совокупный, тогда использование S s = { arguments_opt }; не вызывает Sконструктор. Вместо этого он вызывает то, что называется агрегатная инициализация. Агрегаты являются единственными классами, так что объекты этого класса могут быть созданы без вызова конструктора.

Только если S является не совокупность, делает S s = { arguments_opt }; попытаться сопоставить список аргументов с параметрами конструктора S,

(Как объяснено другими, в C ++ 11 обеспечение скобки или равно-инициализатор для нестатического члена данных делает класс не агрегатным).

2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector