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; }