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