1

I am trying to override operator+ and operator= for my classes. This is my code:

#include <iostream>
#include <vector>

using namespace std;

class Integer {
public:
    int i;
    Integer operator+ (Integer&);
    Integer& operator= (Integer&);
};

Integer Integer::operator+(Integer& rhs) {
    Integer res;
    res.i = this->i + rhs.i;

    return res;
}

Integer& Integer::operator=(Integer& rhs) {

    this->i = rhs.i;
    return *this;
}

int main()
{
    Integer i1, i2, i3;
    i1.i = 1, i2.i = 2;
    i3 = i1 + i2;
    cout << i3.i;
}

In visual studio 2017, the compiler complained that:

"E0349  no operator "=" matches these operands"

It seems that an Integer object doesn't match with Integer& in the operator= function. But it works for operator+ function. It is very confusing.

Thanks a lot.

Swapnil
  • 1,424
  • 2
  • 19
  • 30
Poi
  • 19
  • 1
  • 1
    `i1 + i2` (logically) stores its result in a temporary. `i3 = i1 + i2` needs to poass a reference to that temporary to `operator=()`. References to temporaries must be `const`. Your `operator=()` accepts a non-`const` reference, so is not a valid match. `i1` and `i2` are named, so can be passed by non-`const` reference to `operator+()`. It is a good ideal to `const`-qualify references when the object past is not expected to be changed - this is true for both `operator=()` and `operator+()` functions. – Peter Sep 22 '18 at 01:41
  • 1
    Much wisdom on this and other operators can be found at [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) – user4581301 Sep 22 '18 at 02:52

2 Answers2

3
i3 = i1 + i2;

returns a temporary variable of type Integer.

Now, your operator= takes a Integer&. This is a reference to an Integer. The problem is that temporaries cannot bind to non-const references.

Just make sure you change to const Integer&. That is the default for all operator overloads anyway.

DeiDei
  • 10,205
  • 6
  • 55
  • 80
2

I'll break this down from the assignment statement.

i3 = i1 + i2;

The first thing that happens were is the addition expression gets evaluated. That's this code snippet:

i1 + i2

You designed your operator overload to handle this expression. Your custom addition operator overload returns a new Integer instance. But the problem occurs when you try to assign this new instance to the parameter in your assignment overload. Here's a snippet of that code.

Integer& Integer::operator=(Integer& rhs);

When you use a referenced parameter in a function declaration, the compiler checks to make sure that this value is not a temporary value, so that it will exist after the function is called. The compiler has determined (correctly) that the argument passed to this assignment statement is a temporary value. That is why it spits out an error when you try to do this.

The most logical why I see of making your code make sense is to implement the following:

Integer& Integer::operator=(const Integer& rhs) {
    this->i = rhs.i;
    return *this;
}

By adding the const-specifier, you tell the compiler that you're not relying on rhs to persist existence after calling the function. In that case, the value passed to the parameter may be a temporary value.

tay10r
  • 4,234
  • 2
  • 24
  • 44
  • Your last sample for `Integer::operator=()` is a counter example? If so, please, mention it explicitly. It returns a reference to a local variable (`result`). This is [Undefined Behavior](https://stackoverflow.com/a/4105123/1505939) because once you have left the body of `operator=()` `result` goes out of scope and the returned reference becomes dangling. – Scheff's Cat Sep 22 '18 at 04:57
  • @Scheff thanks for pointing this out. It looks like the code from the addition operator overload, I must've mixed them up some how without realizing it. I'm actually quite surprised it wasn't down voted. Fixing it now. – tay10r Sep 22 '18 at 12:44