class X { X operator-() const; X operator&() const; }; class Y { friend Y operator- (const Y & ); friend Y operator& (const Y & ); };
Another important unary operator is logical negation, operator !.
class X { X operator+( const X& ) const; X operator&( const X& ) const; }; class Y { friend Y operator+ (const Y &, const Y & ); friend Y operator& (const Y &, const Y & ); };In general, it is not necessary to have the non-member functions as friends, but if any of the private data members of the operands needs to be accessed, this is a necessity.
Binary operators are usually defined as friends (non-members), for symmetry. This is recommended for commutative operators such as arithmetic operators. Unary operators are usually represented as members.
Adapted from Paul J. Lucas, "The C++ Programmer's Handbook", AT & T
The following example shows how operator * can be defined for strings. Notice that a string literal like "hello" is not of type string in C++, but of type char * and is stored as a zero-terminated array of characters, with the zero character at the end, i.e. as 'h', 'e', 'l', 'l', 'o', '\0' .
Operators cannot be redefined for built-in types in C++, so we cannot make "hello" * 3 work -- that would require defining operator* ( char *, int ), but neither of the two arguments is of a class type. Still, we can make it work a variable of type string and an int:
#include <iostream.h> #include <string> string operator*( const string& s, int n ){ string res = ""; for( int i=0; i < n; i++ ) res += s; return res; } int main(){ string s = "hello"; cout << s * 3 << endl; return 0; }which prints "hellohellohello", as we wanted.
Sources:
The output of running main_frac.cpp follows. Notice the calls to destructor that show when temporaries returned by overloaded operators get destroyed. The order in which things happen is completely determined at compile time, so all calls to the destructor were inserted by the compiler into the executable at the corresponding places.
Exercises:
Test 1: myFrac other constructor called myFrac other constructor called myFrac default constructor called myFrac other constructor called operator= for myFrac myFrac destructor called 1/2 + 1/3 = 5/6 Test 2: myFrac copy constructor called myFrac other constructor called 1/4 myFrac destructor called Test 3: myFrac other constructor called myFrac other constructor called myFrac other constructor called x = 2/5 y = 5/1 z = 3/1 Test 4: myFrac other constructor called myFrac other constructor called myFrac other constructor called 144/144 myFrac destructor called myFrac destructor called myFrac destructor called Test 5: myFrac other constructor called myFrac other constructor called myFrac destructor called 3/2 That's All Folks! Time to destroy variables... myFrac destructor called myFrac destructor called myFrac destructor called myFrac destructor called myFrac destructor called myFrac destructor called myFrac destructor called myFrac destructor called