February 27, 2002
Reading assignment:
  Deitel and Deitel - 8.1-8.3 and 8.7-8.8
  -or-
  Other texts: overloading binary operators, the copy constructor

Warm-up: I'll hand back exams and we'll do the last problem together

Why do we want/need to overload operators? Some examples:
   - If we have two strings, s1 and s2, we can say
     if (s1==s2) cout << s1;
     or cout << s[0];
     We can do this because the string class "overloaded" the operators
     ==, <<, and []. In other words, the string class includes code that
     says what to do if you use ==, <<, or [] with strings.  This makes the
     string class useful
   - We wrote a class called Ratnum.  Say if have two Ratnum objects, r1 and r2
     If I write any of the following
     if (!r1) cout < "urp";
     if (r1 == r2) cout << "yah, man";
     r1 = r1 + r2;
     r1 += r2;
     cout << r1 << r2;
     the compiler will give me an error.  Why?  Because we did not overload
     the ! operator, the + operator, += operator, << or >>.  This severely
     limits the usefulness of our Ratnum class.
   - On the other hand, if we say
     r1 = r2;
     the compiler will not complain, even though we didn't overload
     the assignment operator!  The compiler always creates a default assignment
     operator for a class, which just copies all the data members.  This can
     be an advantage because it saves us from overloading the assignment
     operator, but if member-wise copy is not what we want, then we'd better
     overload the assignment operator to do what we want.  If our class
     contains pointer data members, then we almost always want to do this.
   - Another default function the compiler provides for classes is a default
     copy constructor.  This does a memberwise copy.  The copy constructor
     gets called whenever you initialize an object to be a copy of an existing
     object of the same class, whenever an object is sent as a parameter to a
     function, and whenever an object is returned by a function.  If our
     class contains pointer data members, then we don't want to use the
     default copy constructor, and we must override it.
   - Some of the operators we need to overload (such as !) are unary operators
     (they operate on only one value), and others are binary operators
     (such as +, ==, or =) which operate on two values.  The syntax for these
     two cases is slightly different.  Today we'll learn how to overload
     binary operators.  See your text for a list of all operators that you may
     overload.
   - Let's start with overloading the operator + and == (because they're
     easier than overloading =) The first thing you need to know is that
     if x and y are objects of type class fooclass, and if you say x + y,
     the compiler secretly thinks of it as x.operator+(y), where operator+ is
     a member function of fooclass.  Now guess what it does with (x==y).
     (x.operator==(y)).  So all we need to make such a member function
     (it can also be done with a friend function - read about it and you're
     free to do it that way instead) Notice that we use the member function
     for the left-hand operand
   - Let's overload the + and == operators for a class of complex numbers

    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);
        bool operator==(const Complex &c) const {return (c.real==real &&c.imag==imag);};
     private:
        float real;
        float imag;
     };

     Complex Complex::operator+(const Complex &c)
     {
         Complex ans;
         ans.real = real+c.real;
         ans.imag = imag+c.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;
         if (c4==c2) cout << "Yeah! == works! " << endl;
         if (!(c1==c2)) cout << "Yeah! == works" << endl;
         return 0;
    }