4

I realize that there are examples after examples of overloading the assignment operator on the web, but I have spent the last few hours trying to implement them in my program and figure out how they work and I just can't seem to do it and any help would be greatly appreciated.

I am trying to implement an overloaded assignment operator function.

I have 3 files working, the Complex.h header file, a Complex.cpp definition file, and a .cpp file I'm using as a driver to test my Complex class.

In the Complex.h header file my prototype for the assignment operator:

Complex &operator= (Complex&); 

And so far what I have for the definition of the overloaded operator in my .cpp file is:

 Complex &Complex::operator=(Complex& first) { if (real == first.real && imaginary == first.imaginary) return Complex(real, imaginary); return first; }; 

And the way I'm calling my assignment operator in my functions is:

 x = y - z; 

So specifically, my problem is that when I call the overloaded assignment operator with x = y -z, it doesn't assign the passed in value to x when I return the passed in value and I'm unable to figure out why from numerous examples and explanations on the web, any help would be greatly appreciated and I thank you for any help ahead of time.

7
  • 1
    Why don't you read some of those examples after examples and model your assignment operator on one that actually works? Commented Mar 28, 2015 at 16:03
  • = shouldn't probably modify its right hand operand. Commented Mar 28, 2015 at 16:03
  • @juanchopanza I tried that, and I apologize for this and sincerely appreciate your input, but my brain just doesn't work this way, I did try to read those examples and model after those working examples but it would end in recursion. Commented Mar 28, 2015 at 16:08
  • @zenith So you're saying that by returning first I am modifying the right hand operand? Commented Mar 28, 2015 at 16:08
  • No, he clearly does not modify the right-hand-operand. Commented Mar 28, 2015 at 16:09

3 Answers 3

4

I think you need the following operator definition

Complex & Complex::operator =( const Complex &first ) { real = first.real; imaginary = first.imaginary; return *this; }; 

You have to return reference to the object that is assigned to. Also the parameter should be a constant reference. In this case you may bind the reference to a temporary object or you have to write also a move assignment operator.

In your implementation of the copy assignment operator you do not change the assigned object.:) You simply create a temporary and return reference to this temporary or return reference to first.

Sign up to request clarification or add additional context in comments.

6 Comments

Whilst strictly accurate, this isn't that helpful as it doesn't really explain to the OP why you've written it that way.
If I understand your method correctly I should assign to the real and imaginary private data members to create a new Complex object and then return the created Complex object with the address of the current (this) data member?
@DastardlyDeedDoer No, assignment should not create a new object (unless as an intermediary implementation detail). It assigns a value to an existing one.
@juanchopanza You're saying I'm creating a new object by returning first? But isn't it already created because I called the overloaded operator with it? So I'm just returning the passed in value? Or is my understanding of this way off?
@DastardlyDeedDoer No, I am saying you don't create an new object and you shouldn't. I mean, you in your broken code do, but the code in this answer doesn't.
|
1

Assignment takes in two objects, the object to be assigned to, and the object with the desired value.

Assignment should:

  • modify an existing object, the object being assigned to

Assignment should not:

  • create a new object
  • modify the object that has the desired value.

So let's say the object type we're dealing with is:

struct S { int i; float f; }; 

A function that performs assignment might have the signature:

void assignment(S &left_hand_side, S const &right_hand_side); 

And it would be used:

S a = {10, 32.0f}; S b; assignment(b, a); 

Notice:

  • the left hand side object is modifiable, and assignment will modify it, rather than create a new object.
  • the right hand side object, the object with the desired value, is not modifiable.

Additionally, in C++ the built-in assignment operation is an expression rather than a statement; it has a value and can be used as a subexpression:

int j, k = 10; printf("%d", (j = k)); 

This sets j equal to k, and then takes the result of that assignment and prints it out. The important thing to note is that the result of the assignment expression is the object that was assigned to. No new object is created. In the above code, the value of j is printed (which is 10, because j was just assigned the value 10 from k).

Updating our earlier assignment function to follow this convention results in a signature like:

S &assignment(S &left_hand_side, S const &right_hand_side);

An implementation looks like:

S &assignment(S &left_hand_side, S const &right_hand_side) { // for each member of S, assign the value of that member in // right_hand_side to that member in left_hand_side. left_hand_side.i = right_hand_side.i; left_hand_side.f = right_hand_side.f; // assignment returns the object that has been modified return left_hand_side; } 

Note that this assignment function is not recursive; it does not use itself in the assignment, but it does use assignment of the member types.

The final piece of the puzzle is getting the syntax a = b to work, instead of assignment(a, b). In order to do this, all you have to do is make assignment () a member function:

struct S { int i; float f; S &assignment(S &left_hand_side, S const &right_hand_side) { left_hand_side.i = right_hand_side.i; left_hand_side.f = right_hand_side.f; return left_hand_side } }; 

Replace the left_hand_side argument with *this:

struct S { int i; float f; S &assignment(S const &right_hand_side) { this->i = right_hand_side.i; this->f = right_hand_side.f; return *this; } }; 

And rename the function to operator=:

struct S { int i; float f; S &operator=(S const &right_hand_side) { this->i = right_hand_side.i; this->f = right_hand_side.f; return *this; } }; int main() { S a, b = {10, 32.f}; S &tmp = (a = b); assert(a.i == 10); assert(a.f == 32.f); assert(&tmp == &a); } 

Another important thing to know is that the = sign is used in one place that is not assignment:

S a; S b = a; // this is not assignment. 

This is 'copy initialization'. It does not use operator=. It is not assignment. Try not to confuse the two.

Points to remember:

  • assignment modifies the object being assigned to
  • assignment does not modify the object being assigned from.
  • assignment does not create a new object.
  • assignment is not recursive, except insofar as assignment of a compound object makes use of assignment on all the little member objects it contains.
  • assignment returns the object after modifying its value
  • copy initialization looks sort of like assignment, but has little to do with assignment.

1 Comment

I know this was posted awhile back - but its a really thoughtful answer and should be preserved.
0

An overloaded assignment operator should look like this:

Complex &Complex::operator=(const Complex& rhs) { real = rhs.real; imaginary = rhs.imaginary; return *this; }; 

You should also note, that if you overload the assignment operator you should overload the copy constructor for Complex in the same manner:

Complex::Complex(const Complex& rhs) { real = rhs.real; imaginary = rhs.imaginary; }; 

12 Comments

This is a double fail. First, you overloaded = but made it do ==, and secondly, self-assignment is for out-of-date lecturers and not for real-world use
I have the code for the equality operator working just fine in later code, I need to be able to modify the left hand operand (the x) when I return the value from the assignment operator function.
@DastardlyDeedDoer "I need to be able to modify the left hand operand (the x) when I return the value from the assignment operator function." My example will exactly do this.
@Puppy I totally agree and that is a major reason I'm here asking for help, all of the coding I do doesn't do such round about crap. But this is for a class I'm taking and I will get little credit if I don't get this too work. But mostly my reason for the use of the equality operator is to avoid self-assignment, unless I'm going about that the wrong way too.
@Puppy There is a very important use case where you simply have to check for self-assignment: Job interviews. ;-)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.