Ответ 1
Определение для конструктора преобразования отличается от С++ 03 и С++ 11. В обоих случаях он должен быть конструктором не explicit
(иначе он не будет задействован в неявных преобразованиях), но для С++ 03 он также должен быть вызван с помощью одного аргумента. То есть:
struct foo
{
foo(int x); // 1
foo(char* s, int x = 0); // 2
foo(float f, int x); // 3
explicit foo(char x); // 4
};
Конструкторы 1 и 2 - оба преобразования конструкторов в С++ 03 и С++ 11. Конструктор 3, который должен принимать два аргумента, является только конструктором преобразования в С++ 11. Последний, конструктор 4, не является конструктором преобразования, потому что он explicit
.
-
С++ 03: §12.3.1
Конструктор, объявленный без функции-спецификатора
explicit
, который может быть вызван одним параметром, указывает преобразование из типа его первого параметра в тип его класса. Такой конструктор называется конструктором преобразования. -
С++ 11: §12.3.1
Конструктор, объявленный без функции-спецификатора
explicit
, указывает преобразование из типов его параметров в тип своего класса. Такой конструктор называется конструктором преобразования.
Почему конструкторы с более чем одним параметром считаются преобразователями в С++ 11? Это связано с тем, что новый стандарт предоставляет нам удобный синтаксис для передачи аргументов и возврата значений с помощью braced-init-lists. Рассмотрим следующий пример:
foo bar(foo f)
{
return {1.0f, 5};
}
Возможность указывать возвращаемое значение в виде списка бит-init считается преобразованием. Это использует конструктор преобразования для foo
, который принимает float
и int
. Кроме того, эту функцию можно вызвать, выполнив bar({2.5f, 10})
. Это также конверсия. Поскольку они являются преобразованиями, имеет смысл для конструкторов, которые они используют для преобразования конструкторов.
Поэтому важно отметить, что создание конструктора foo
, который принимает float
и int
, имеет спецификатор функции explicit
, который бы остановил вышеуказанный код от компиляции. Вышеупомянутый новый синтаксис может использоваться только в том случае, если для выполнения задания имеется конструктор преобразования.
-
С++ 11: §6.6.3:
Оператор
A
return
с бин-init-list инициализирует объект или ссылку, возвращаемую из функции путем инициализации-списка-инициализации (8.5.4) из указанного списка инициализаторов.§8.5:
Инициализация, возникающая [...] при передаче аргументов [...], называется копированием-инициализацией.
§12.3.1:
Явный конструктор строит объекты так же, как неявные конструкторы, но делает это только там, где явно используется синтаксис прямой инициализации (8.5) или где применяются приведения (5.2.9, 5.4).