In class four, we continue our look at operator overloading.
We introduce reference variables and look at the assignment operator.


Operator overloading summary 1. Overloaded operators are converted to function calls. 2. Precedence, associativity and number of arguments are preserved. 3. Most operators can be defined as member functions or not Assignment, function call, subscript and pointer dereference MUST be member functions 4. Must have one operand that is user-defined. i.e., we can't overload * for ints 5. Can't create new operators

Operator defined as an ordinary function

Rational operator* (const Rational& lhs, const Rational& rhs) { // construct a new Rational and return it return Rational (lhs.num() * rhs * num(), lhs.den() * rhs.den() ); } Since multiplication is a binary operator, there are two parameters, the left-hand operand (lhs) and the right-hand operand (rhs). This function is not in the class definition. It is not associated with any particular object. It's just like any other function you might write. It takes two Rational objects as parameters and returns a Rational object. It must use the accessor functions num() and den() for each Rational. This function is simply put into a .C (or .h) file and will be used by the compiler when we write "x * y".

Operator as a member function

Function prototype within the class definition

class Rational { private: ...... ...... public: ...... ...... Rational operator * (const Rational& rhs); ..... };

the implementation -- .C or .h file

Rational Rational::operator* (const Rational& rhs) { return Rational (num * rhs.num(), den * rhs.den()); }

This binary operator has only one parameter. Why?


Operator as a friend function

// friend declaration in the class definition -- rational.h // BUT friends are NOT part of the class. So what??

class Rational { private: ….. ….. public: ….. ….. friend Rational operator * (const Rational&, const Rational&); ….. };

// Implementation in .C or .h file

Rational operator* (const Rational& lhs, const Rational& rhs) { return Rational (lhs.num * rhs.num, lhs.den, rhs.den); }

The class decides which functions are its friends. Friends have direct access to private members.


An interesting question ---

We now have the tools to multiply two Rationals and get a Rational object as the result. But, do we always want to multiply Rational objects? Suppose we want to multiply a Rational and an integer. Can we do it? Sometimes -- consider the following code fragment. Rational x(5, 9); Rational y(3,4); Rational z; z = x * y; // No problem y = x * 7; // yes -- why?? y = 7 * x; // It depends -- on what?

What do we need to provide to enable us to do the 2nd multiplication?


Now we are in a position to write the statement z = x * y; What happens when it is executed? 1. a new Rational is created by the operator* function 2. it is copied (member-wise) to z BUT look closer --- C++ is call by value -- the arguments lhs and rhs are copies of x and y, so really the following occurs 1. x is copied to lhs 2. y is copied to rhs 3. x * y is copied to a temporary 4. the temporary is copied to z For large class, this copying is expensive. We can avoid this expense by using "references" as arguments A reference is an "alias" for a variable. Whatever you do to the reference applies to the variable… sort of like an automatically dereferenced pointer.

ASSIGNMENT OPERATOR

C++ provides a default he assignment operator (i.e =). It is a member-wise copy. This is not always what we want -- more on this later. main ( ) { Rational x (5, 9); Rational y = x; // initialization, NOT assignment Rational z; z = x; // assignment z = 5; // assignment } QUESTION : How does z = 5; happen? ANSWER: INITIALIZATION is NOT Assignment. If overloaded, the assignment operator MUST be a member function
// Assignment operator for Rational // the message is "assign this Rational to yourself" Rational& Rational::operator = (const Rational& rhs) { num = rhs.num(); den = rhs.den(); return *this; } QUESTION: This routine's return type is Rational&. How is *this a Rational& ? Why does this function return Rational& ?