Инициализация копирования C++ + неявный вызов конструктора = ошибка
Этот код:
class foo
{
int x;
public:
foo(int x) : x(x) { }
int get() const { return x; }
//...
};
class bar
{
int x;
public:
bar(const foo& x) : x(x.get()) { }
int get() const { return x; }
bar& operator =(const foo& rhs) { x = rhs.get(); return *this; }
//...
};
void func()
{
foo f = 3;
bar b = 3;
b = 7;
//...
}
ошибки на bar b = 3
строка (g++ 4.7.1 с -fstd=gnu++11
):
error: conversion from 'int' to non-scalar type 'bar' requested
Тем не менее, я предоставляю bar
конструктор, который принимает foo
и целые числа могут быть неявно преобразованы в foo
как показано линией, предшествующей ему. Так что же не так?
Кстати, по нескольким причинам нежелательно форсировать конвертацию в foo
с помощью foo(3)
потому что это сделало бы мой код ужасным для использования и чтения.
2 ответа
Я предоставляю конструктор bar, который принимает foo, и целые числа могут быть неявно преобразованы в foo, как показано строкой, предшествующей ему. Так что же не так?
Цепное преобразование не разрешено в C++, что означает, что (цепное) преобразование не может быть выполнено:
int -> foo -> bar //not allowed (chained conversion)
даже если дано следующее:
int -> foo //given
foo -> bar //given
Так что если вы хотите int -> bar
работать, а затем добавить еще один конструктор, принимая int
к классу bar
,
§ 13.3.3.1.2/1 о неявных определяемых пользователем последовательностях преобразования мандатов:
Определяемая пользователем последовательность преобразования состоит из начальной стандартной последовательности преобразования, за которой следует определенное пользователем преобразование (12.3), за которым следует вторая стандартная последовательность преобразования. Если определяемое пользователем преобразование определяется конструктором (12.3.1), начальная стандартная последовательность преобразования преобразует тип источника в тип, требуемый аргументом конструктора. Если определяемое пользователем преобразование определяется функцией преобразования (12.3.2), исходная стандартная последовательность преобразования преобразует тип источника в неявный параметр объекта функции преобразования.
Это означает, что невозможно связать более одного пользовательского преобразования.