2015-01-25 1 views
0

Следующие программы печатает 42:Прямая инициализация объекта против инициализации с Convertion функций

#include <iostream> 

struct A 
{ 
    operator int(){ return 42; } 
}; 

struct B 
{ 
    operator A(){ return A(); } 
}; 

B b; 
int a = A(b);  
int main(){ std::cout << a << std::endl; } //42 

DEMO

Но если мы попытаемся определить совладать/ход или оба contructors он не будет работать.

#include <iostream> 

struct A 
{ 
    A(A&&){ std::cout << "A(A&&)" << std::endl; } 
    A(A&){ std::cout << "A(A&)" << std::endl; } 
    operator int(){ return 42; } 
}; 

struct B 
{ 
    operator A(){ return A(); } 
}; 

B b; 
int a = A(b); 

int main(){ std::cout << a << std::endl; } //Error 

DEMO

я подумал, соответствующий раздел, описывающий, что поведение является N4296::8.5/17.7 [dcl.init]

If the destination type is a (possibly cv-qualified) class type:

[...]

— Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion functions are enumerated (13.3.1.5), and the best one is chosen through overload resolution (13.3). The user-defined conversion so selected is called to convert the initializer expression into the object being initialized. If the conversion cannot be done or is ambiguous, the initialization is ill-formed.

Она не должна в зависимости от отсутствия/присутствия конструкторов. Нам просто нужно иметь соответствующие функции преобразования, чтобы выбрать последовательность преобразования.

ответ

1

Вы фактически удалили конструктор по умолчанию. Из стандарта (12.1/4, курсив мой):

A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted

ЕСЛИ нет пользователем объявлен конструктор. Но вы объявили два, поэтому нет неявного конструктора по умолчанию. Таким образом, это:

operator A(){ return A(); } 
        // ^^^ 

не удается скомпилировать. Вот почему возникает ошибка:

error: no matching function for call to A::A()

Код пытается вызвать оператора преобразования, но тело недействительно.

+0

Кроме того, если у вас есть только конструктор 'A :: A (A &)', а не 'A :: A (A &&)' компиляция конструктора, все равно будет работать (после добавления конструктора A :: A() "), потому что ваш' B :: operator A() 'возвращает не-const rvalue, а ссылка A &' не может быть привязана к нему. Важно думать, что конструктор 'A' принимает значение rvalue, например. 'A :: A (A &&)' или 'A :: A (const A &)' – robal

Смежные вопросы