Почему ошибка в параметре типа ссылка?
class m {
public:
int n;
m(int n) :n(n) {};
m(m& nn) {
n = nn.n;
}
m operator=(m& ex);
};
m m::operator=(m& ex) {
this->n = ex.n;
return n;
}
m f() {
m k(8);
return k;
}
ostream& operator<<(ostream& os, m& ex) {
os << ex.n<<endl;
}
int main() {
m m1(1), m2(2);
m1 = f();//вернулся тип m, а дальше просто как обычная передача
//параметра по ссылке, чтобы не занимать место
cout << m1;
}
почему ошибка=бинарный "=": не найден оператор, принимающий правый операнд типа "m" (или приемлемое преобразование отсутствует)
есть же такое
int foo(int& v){
++v;}
int main(){
int x=9;
foo(x)// здесь же тоже не ссылочный тип
}
Ответы (2 шт):
m1 = f();
Здесь вызывается оператор присваивания, у вас имеющий вид
m m::operator=(m& ex) {
this->n = ex.n;
return n;
}
Заметим, что ваша функция m f() возвращает значение (временное) типа m. А объявление оператора присваивания ясно говорит, что при присваивании присваиваемый аргумент может изменяться, он не константный. То, что он не изменяется — это неважно, важно, что своим (m& ex) вы оставляете такую возможность.
Чтобы было понятнее, представьте себе, что это int, функция возвращает, например, 2, но при присваивании это 2 должно изменяться. Но ведь переменной, которая бы хранила двойку, просто нет! Так понятнее?
Вот если бы вы объявили (оставим возврат еще одного временного объекта m после присваивания на ваше усмотрение, заметим только, что это лишает вас возможности использовать цепочку присваивания `a = и = сё)
m m::operator=(const m& ex)
то тогда дело другое.
В примере с int дело другое:
int foo(int& v) { ++v; }
int main(){
int x=9;
foo(x);
}
x, будучи переменной, запросто превращается в ссылку. А вот попробуйте вызвать здесь foo(4) — и вы увидите, что это не работает. Или хотя бы foo(foo(x)).
Формальный ответ вам дал user7860670 в комментариях, я же постарался просто расписать его понятнее.
Аргумент m & ex в m operator=(m& ex); может быть предоставлен только объектом со стабильным временем жизни lvalue. А возвращаемое значение функции m f() возвращает всегда временное значение rvalue.
Ссылки на эти типы несовместимы и надо отдельно писать разные функции. Вариант универсальности будет если аргумент константный.
Только для lvalue :
m operator=(m & ex);
Только для rvalue :
m operator=(m && ex);
Для всех :
m operator=(m const & ex);