March 8, 2002 Reading assignment: Deitel and Deitel - Read 8.5 Other texts - overloading the << and >> operators Overloading the << operator - We'll overload the << operator for the class Complex, shown here class Complex { friend ostream &operator<<(ostream &out, const Complex &c); friend istream &operator>>(istream &in, Complex &c); public: Complex(float r=0, float i=0) {real=r, imag = i;} Complex operator+(const Complex &c) const; bool operator==(const Complex &c) const {return (c.real==real &&c.imag==imag);}; // etc., other member functions left off for brevity private: float real; float imag; }; Complex Complex::operator+(const Complex &c) const { Complex ans; ans.real = real+c.real; ans.imag = imag+c.imag; return ans; } ostream &operator<<(ostream &out, const Complex &c) { out << c.real; if (c.imag) cout << " + " << c.imag << 'i'; return out; } istream &operator>>(istream &in, Complex &c) { float real_part(0), imag_part(0); char ch1, ch2; // read in the real part, the plus sign, the imaginary part, and an 'i' in >> real_part >> ch1 >> imag_part >> ch2; c.real = real_part; c.imag = imag_part; return in; } - Remember that if we say x op y, the compiler translates it to x.operator op(y) In other words, the member function operator op is called for the left operand But when we say cout << obj, the left operand is cout, not obj. This means that we can't implement it as a member function of obj. Instead, we overload << with a non-member function. If such a function has been written, then the compiler will turn x.operator op(y) to operator op(x,y) - This non-member function must take the two operands as parameters. Remember that cout is an ostream, so the first parameter is an ostream. This first parameter cannot be const, since we are altering it by writing to it! The second parameter is the object, in our case, a Complex object. It should be const, because the object itself should not be altered just because we are displaying it. - We want to be able to cascade << (like the case of the assignment operator), so the function must return a reference to the ostream - Since the function is no longer a member function, we don't have to worry about whether the function itself should be declared const - The declaration is thus ostream &operator<<(ostream &out, const Complex &c); - If we make this a friend function, then it can access the data members and display them - Now we can output complex numbers with code such as: Complex c1(2,4); cout << c1; Overloading the >> operator - We'll now overload the >> operator for the class Complex - Again, this non-member function must take the two operands as parameters. Remember that cin is an istream, so the first parameter is a (non-const) istream &. As before, the second parameter is a Complex &, but this time we expect the second parameter to be changed, so it is no longer const - We want to be able to cascade >> as well, so the function must return a reference to the istream - The declaration is thus istream &operator>>(istream &input, Complex &c); - If we make this a friend function, then we can set the private data members to the values input from the stream - Look at the function definition - note that it currently does no error checking and requires you to enter a real and imaginary part (even for 0+0i) - Now we can output complex numbers with code such as: Complex c1; cin >> c1;