0

I am trying to understand overloading operators in c++. I've written some code below trying to overload the = operator. However, it doesn't work correctly and I am wondering why now.

I've followed the example that is provided here for the + operator.

Operators Overloading in C++

#include <iostream>
using namespace std;

class Test {
private:
    int id;
    string name;

public:
    Test(): id(0), name(""){

    }

    Test(int id, string name): id(id), name(name) {

    }

    void print() {
        cout << id << ":" << name << endl;

    }
    Test operator=( Test &other) {

        Test test;
        cout << "Assignment running" << endl;

        test.id =other.id;
        test.name =other.name;

        return test;

    }
};

int main() {

    Test test1(10, "Mike");
    cout << "Print Test1" << endl;
    test1.print();

    Test test2;

    test2.operator=(test1);
    cout << "Print Test2" << endl;
    test2.print();


    cout << endl;

}
Tom Dara
  • 61
  • 8
  • 3
    `test2.operator=(test1);` the whole point of overloading an operator is so you can call it like `test2 = test1` and not like a function-call... – tkausl Dec 11 '17 at 11:56
  • You didn't consider looking at the example of overloading the assignment operator? – molbdnilo Dec 11 '17 at 12:05
  • Possible duplicate of [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) – 463035818_is_not_an_ai Dec 11 '17 at 12:12
  • Since you're in discovery mode, note how `operator=` is not quite synonymous to a constructor with the same parameter type. – Michaël Roy Dec 11 '17 at 13:31

3 Answers3

4

operator=, by standard, should modify this, and return a reference to *this (in order to allow for compound assignments):

Test& operator=(const Test& other) {
    cout << "Assignment running" << endl;

    this->id = other.id;
    this->name = other.name;

    return *this;
}

Note that I'm also passing other as const. Your version does not modify this, which will have surprising effects.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
3

Because unlike +, = needs to modify the object in question, rather than a temporary variable that you then return.

Test& operator=(const Test &other) {

    cout << "Assignment running" << endl;

    id =other.id;
    name =other.name;

    return *this;
}
Steve
  • 1,747
  • 10
  • 18
  • 1
    Technically, it doesn't have to modify the object in question, that's why the compiler accepted the code in the question. But it clearly was the intent. – MSalters Dec 11 '17 at 11:58
1

Start by thinking about what semantics you expect. Since the whole point of overloading operators is that you can use the same syntax as built-in operators, replace

test2.operator=(test1);

with

test2 = test1;
  • First, what do you expect to happen to test1 in this expression? Should it change?

    Hint: the answer is no, so the right-hand-side parameter should be passed by const reference.

  • Secondly, what do you expect to happen to test2 in this expression? Should it change?

    Yes, of course it should change, you're assigning to it. So, the left-hand-side argument should be modified by your code. Note that in a member operator, the left-hand side is this.

So, we know we should at least change your code to take the right-hand-side parameter by const reference, and that it ought to modify this rather than leaving it untouched while assigning to a temporary.

Further, the canonical forms of all these operators are well-known and documented. For example, here

Test& operator=(const Test &other) {
    cout << "Assignment running" << endl;

    this->id =other.id;
    this->name =other.name;

    return *this;
}
Useless
  • 64,155
  • 6
  • 88
  • 132
  • why do you have to pass other by reference and not by value? both ways work. – Tom Dara Dec 11 '17 at 12:36
  • Passing the RHS by value is also semantically fine, but could be expensive for large objects, and there's no real benefit. In this case, it includes copying a string, which likely involves a dynamic allocation and subsequent deallocation. That's a relatively expensive operation, and one that can fail if you're out of memory. – Useless Dec 11 '17 at 12:45
  • 1
    Passing by value and then moving does have its advantages. Especially when the move operation is noexcept. – Michaël Roy Dec 11 '17 at 13:20
  • 1
    True, but then I should explain the missing move assignment too, and that seemed like more than OP needs at this stage. – Useless Dec 11 '17 at 13:26