March 1, 2002
Reading assignment:
  Deitel and Deitel - 8.1-8.3 and 8.7-8.8 again
  -or-
  Other texts: overloading binary operators


Warm-up: Last time we overloaded the + and == for a class of Complex numbers.
Note that operator+ really should have been a const member function.
Now, overload the - operator in this same class:

    class Complex {
     public:
        Complex(float r=0, float i=0) {real=r, imag = i;}
        void display() const {cout << real << " + " << imag << "i ";}
        void set_real(float r, float im) { real = r; imag = im;}
        Complex operator+(const Complex &c) const;
        Complex operator-(const Complex &c) const;
        bool operator==(const Complex &c) const {return (c.real==real &&c.imag==imag);};
     private:
        float real;
        float imag;
     };

     Complex Complex::operator+(const Complex &right) const
     {
         Complex ans;
         ans.real = real+right.real;
         ans.imag = imag+right.imag;
         return ans;
     }

     Complex Complex::operator-(const Complex &right) const
     {
         Complex ans;
         ans.real = real-right.real;
         ans.imag = imag-right.imag;
         return ans;
     }

     int main()
     {
         Complex c1(2), c2(2,4), c4(2, 4), c3;
         cout << "Testing the + operator: " << endl;
         c3 = c1+c2;
         c1.display(); cout << " + "; c2.display(); cout << " = "; c3.display(); cout << endl;
         c3 = c1-c2;
         c1.display(); cout << " - ("; c2.display(); cout << ") = "; c3.display(); cout << endl;
         if (c4==c2) cout << "Yeah! == works! " << endl;
         if (!(c1==c2)) cout << "Yeah! == works" << endl;
         return 0;
    }   

Notice that having to use the Complex::display operator is really irritating.  It
would be much better if we could just say cout << c1.  This requires overloading the
<< operator, which we'll learn next week.

Now we'll overload  some other operators for the class Complex.  Overloading =, +=,
etc. has an extra complication.  Let's start with the assignment operator.  (Please
note that this is not actually necessary for class Complex - because the assignment
operator is automatically provided (member-wise copy) in a reasonable way for classes
that contain no pointer data members.)
If I say a=b, the compiler translates it to a.operator=(b).  So we have to create
a member function called "operator="  Our first guess for the declaration might be
void Complex::operator=(const Complex &);

However, it has to satisfy an extra requirement - we have to be able to
"cascade" assignments
    x = y = z;  (which means x = (y = z);)
So after doing the assignment (changing the value of a to the value of b), if we return
a copy of the left-hand variable, then this allows us to subsequently assign it to
another variable.  Our second guess for the declaration is
Complex &Complex::operator=(const Complex &)

On the other hand, if we write
   (x = y) = z;
this shouldn't even compile, because (x=y) is not an lvalue.  We can avoid this problem
by making the return value const - here's the final definition:

const Complex &Complex::operator=(const Complex&right)
{
    if (this != &right) {        // if the left and right are the same, then don't copy
        real = right.real;       // do a memberwise copy
        imag = right.imag;
    }
    return (*this);             // this enables cascaded calls
}

Now here's an overloading of += (note that this function returns a constant - which
disables statements such as (x+=y)+=z

const Complex &Complex::operator+=(const Complex &right)
{
    real += right.real;  // add components of right operator to
    imag += right.imag;  // the components of this operator
    return *this;
}