Ошибка компиляции C ++: невозможно преобразовать из B в A, нет конструктора или неоднозначность перегрузки конструктора - PullRequest
7 голосов
/ 16 октября 2019

У меня есть некоторый код, который подразумевает преобразование типа, которое не компилируется, хотя есть метод преобразования ...

class A
{
public:
    A(void) :_m(0) { }
    A(int val) : _m(val) {}
private:
    int _m;
};
class B
{
public:
    B(void) : _m(0) {}
    B(int val) : _m(val) {}
    B(const A&);
    // there is a direct conversion operator here
    operator A(void) const { return A(_m); }
    operator int(void) const { return _m; }
private:
    int _m;
};
int main()
{
    B b;
    A a = (A)b; // error C2440 here
}

Вот сообщение об ошибке:

error C2440: 'type cast': cannot convert from 'B' to 'A'
message : No constructor could take the source type, or constructor overload resolution was ambiguous

Ответы [ 2 ]

2 голосов
/ 16 октября 2019

Сообщение об ошибке означает, что эти два оператора

operator A(void) const { return A(_m); }
operator int(void) const { return _m; }

могут использоваться в выражении

(A)b;

. В результате, используя эти операторы преобразования, можно использовать любой конструктор A( int ) или конструктор копирования по умолчанию A( const A & ).

Чтобы сделать его более понятным, переписать соответствующее объявление, например

A a = A( b );

Так будет ли объект b преобразован в объект типа Aиспользуя первый оператор преобразования или объект типа int, используя второй оператор преобразования.

Вы можете избежать неоднозначности, объявляя операторы, например, такие как

operator A(void) const & { return A(_m); }
operator int(void) const && { return _m; }

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

Вот ваша программа с измененными операторами.

#include <iostream>
class A
{
public:
    A(void) :_m(0) { }
    A(int val) : _m(val) {}
private:
    int _m;
};
class B
{
public:
    B(void) : _m(0) {}
    B(int val) : _m(val) {}
    B(const A&);
    // there is a direct conversion operator here
    operator A(void) const & { return A(_m); }
    operator int(void) const && { return _m; }
private:
    int _m;
};

int main()
{
    B b;
    A a = b; 
    A a1 = B();
}
2 голосов
/ 16 октября 2019

Насколько я понимаю, компилятор пытается интерпретировать несколько путей a = (A)b.

  • , он находит operator A
  • , но также находит operator int на Bи конструктор A(int), который дает ему второй путь B => int => A ...

И он не знает, какой выбрать.

Чтобы исправить компиляцию, я могу:

  • удалить operator int из B
  • переписать строку ошибки как A a = b.operator A(); ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...