Assignment operator overloading: returning void versus returning reference parameter [duplicate]
Asked Answered
C

2

11

Some of the assignment overloading operator examples I see online look like this:

#include <iostream>
using namespace std;

class Distance {
   private:
      int feet;             // 0 to infinite
      int inches;           // 0 to 12
   public:
      // required constructors
      Distance(){
         feet = 0;
         inches = 0;
      }

      Distance(int f, int i){
         feet = f;
         inches = i;
      }

      void operator = (const Distance &D ) { 
         cout << "assigning..." << endl;
         feet = D.feet;
         inches = D.inches;
      }

      // method to display distance
      void displayDistance() {
         cout << "F: " << feet <<  " I:" <<  inches << endl;
      }

};

int main() {
   Distance D1(11, 10), D2(5, 11);

   cout << "First Distance : "; 
   D1.displayDistance();
   cout << "Second Distance :"; 
   D2.displayDistance();

   // use assignment operator
   D1 = D2;
   cout << "First Distance :"; 
   D1.displayDistance();

   return 0;
}

They return void from the overloaded function. This makes sense to me if D1 is the object being called.

Other examples return a reference to a class object.

#include <iostream>
using namespace std;

class Distance {
   private:
      int feet;             // 0 to infinite
      int inches;           // 0 to 12
   public:
      // required constructors
      Distance(){
         feet = 0;
         inches = 0;
      }

      Distance(int f, int i){
         feet = f;
         inches = i;
      }

      Distance& operator = (const Distance &D ) { 
         cout << "assigning..." << endl;
         feet = D.feet;
         inches = D.inches;
         return *this;
      }

      // method to display distance
      void displayDistance() {
         cout << "F: " << feet <<  " I:" <<  inches << endl;
      }

};

int main() {
   Distance D1(11, 10), D2(5, 11);

   cout << "First Distance : "; 
   D1.displayDistance();
   cout << "Second Distance :"; 
   D2.displayDistance();

   // use assignment operator
   D1 = D2;
   cout << "First Distance :"; 
   D1.displayDistance();

   return 0;
}

This does not make sense to me (when taking the first example into consideration). If in the first example D1 = D2; invokes something like D1.=(D2);, why would the second example work in that case? Is it something like D1 = D1.=(D2);? And does it make any difference at the end of the day?

Cyrillic answered 20/2, 2017 at 1:42 Comment(3)
What do you mean ".+"???Pricking
I mean + is the function name. So call D1's + function. Oh I see.. It should be =.... D1's = function... I am editing.Cyrillic
en.cppreference.com/w/cpp/language/copy_assignmentBoner
D
16

Although C++ language lets you overload assignment operator with any return type, including void, you should strongly consider following a widespread convention of returning a reference to the assignee from the operator.

The rationale for it is that

A = B;

will work no matter what the assignment returns, while

A = B = C;

which is a perfect chain of assignments will break, unless B = C returns something assignment-compatible to A (which is usually an object of the same type as A).

Another problem is in situations when you must compare the object as part of a larger expression, for example

mytype obj;
while ((obj = read_obj(cin)) != END_OBJ) {
    ...
}

Hence, the biggest drawback to returning void is inability to chain assignments and use them in places where void is not allowed.

Dremadremann answered 20/2, 2017 at 1:53 Comment(0)
L
5

As a convention, assignment operator usually returns reference (to *this); which makes it possible to chain the assignment, just like the behavior of those built-in types. e.g.

Distance D1, D2, D3;
D1 = D2 = D3;

For D1 = D2;, it's equivalent with D1.operator=(D2);. It doesn't change for the 2nd case, the returned value is just discarded. For D1 = D2 = D3;, it's equivalent with D1.operator=(D2.operator=(D3));. Note the returned value (i.e. reference to D2) is used as the argument for the assignment operator called on D1.

Labia answered 20/2, 2017 at 1:49 Comment(1)
Also you can use it as sub-expression, e.g. while (D1 = D2), or (D1 = D2).foo(), although some style guides discourage that.Extragalactic

© 2022 - 2024 — McMap. All rights reserved.