Operator Overloading for Non-Member Functions

◀ Operator Overloading for Member Functions▶ Traps and Tips
Amazon Let’s discuss how nonmember functions interact with operators. In this case, you need two arguments because the function is independent of Complex. You can do the following:
Complex operator+(Complex & c, Complex & c2); /* function prototype */Complex operator+(Complex & c, Complex & c2) { /* function definition */…	return …}
This is exactly how the aforementioned problem may be solved. If you want a = 5 + b to work, simply declare the first argument to be an int and the second argument to be a Complex object.


On the other hand, let’s say a, b, c are all objects of Complex. Then you only can do
a = b + c;
but not
a = b.operator+(c);
That’s because operator+() is no longer a member of Complex. Another important point to note is that you may not be able to do:
a = a + b + c;
The assignment may or may not work depending on the implementations you are using. If the compiler complains, try taking out ‘&’ in both function prototype and function definition or inserting a ‘&’ between Complex and operator+.


As you can see, member functions and nonmember functions have their advantages and disadvantages. From now on you should be able to make smart decisions about overloading operators!
The following are some common operators that you may overload:

+	=	*=	>>=	>	&	>>	->	<=-	==	/=	<<=	<	|	<<	->*	,*	!=	%=	&=	!	^=	()	new	||/	+=	>=	|=	&&	~=	[]	delete	^%	-=	>>=	~
new and delete are English words, but you still can do

… operatornew(…);… operatordelete(…);

You can pretty much overload any operator the way we just discussed; however, for some of them you should not make their overloaded functions void, particularly <<. If you do so, the function no longer can use multiple operators in a single line, like cout << … << …

Therefore, it is advisable for the overloaded function to return an object.
Here are the general rules regarding operator overloading:
  • Nonmember functions must take exactly 2 arguments, and one of which must be a user-defined type (class or struct); member functions must have 0 or 1 argument (one operand is already a user-defined type).
  • You cannot alter operator context (e.g. cannot make a binary operator become a unary operator) or precedence.
  • You cannot create new operators.
  • You can use only member functions to overload operators =, ->, [], and ().
Here is a sample program that illustrates a member function overloading +:

#include <iostream>using namespace std;class Clock {	int hours;	int minutes;public:	Clock() {};	Clock(int h, int m) { hours = h; minutes = m; }	Clock operator+(Clock & t);	int hr() { return hours; }	int min() { return minutes; }	};Clock Clock::operator+(Clock & t) {	Clock sum;	sum.hours = hours + t.hours + (minutes + t.minutes)/60;	sum.minutes = (minutes + t.minutes) % 60;
return sum;}ostream & operator<<(ostream & os, Clock & t){ os << t.hr() << " hours, " << t.min() << " minutes"; return os;}int main() { Clock a(1, 40); Clock b(3, 29); Clock c(2, 19); cout << a << endl << b << endl << c << endl; a = a + b + c; cout << a << endl; return 0;}
Here is a sample program that illustrates a nonmember function overloading +:

#include <iostream>using namespace std;class Clock {	int hours;	int minutes;public:		Clock() {};	Clock(int h, int m) { hours = h; minutes = m; }	int hr() { return hours; }	int min() { return minutes; }	int set_hr(int h) { hours = h; }	int set_min(int m) { minutes = m; }	};Clock & operator+(Clock & t, Clock & t2) {	Clock sum;	sum.set_hr(t.hr() + t2.hr() + (t.min()+t2.min())/60);
sum.set_min((t.min()+t2.min()) % 60); return sum;}ostream & operator<<(ostream & os, Clock & t){ os << t.hr() << " hours, " << t.min() << " minutes"; return os;}int main() { Clock a(1, 40); Clock b(3, 29); Clock c(2, 19); cout << a << endl << b << endl << c << endl; a = a + b + c; cout << a << endl; return 0;}
Try overloading operators such as -, *, and >> as an exercise, will ya?

◀ Operator Overloading for Member Functions▶ Traps and Tips

fShare
Questions? Let me know!