12.3 MEMBER-FUNCTION OVERLOAD DEFINITIONS FOR OPERATORS


12.3 MEMBER-FUNCTION OVERLOAD DEFINITIONS FOR OPERATORS

In the following implementation of MyComplex, we have provided member function overload definitions for the same operators as in the previous section, except for the output operator ‘<<’. The reason for why the output operator cannot be overloaded as a member function of MyComplex is very important and crucial to understanding the difference between global overload definitions and member-function overload definitions.

 
//OverloadBinaryMemb.cc #include <iostream> using namespace std; class MyComplex { double re, im; public: MyComplex( double r, double i ) : re(r), im(i) {} MyComplex operator+( MyComplex) const; MyComplex operator-( MyComplex) const; // ostream& operator<< ( const MyComplex& ); // WRONG friend ostream& operator<< ( ostream&, const MyComplex& ); //(A) }; MyComplex MyComplex::operator+( const MyComplex arg ) const { //(B) double d1 = re + arg.re; //(C) double d2 = im + arg.im; //(D) return MyComplex( d1, d2 ); } MyComplex MyComplex::operator-( const MyComplex arg ) const { //(E) double d1 = re - arg.re; double d2 = im - arg.im; return MyComplex( d1, d2 ); } ostream&operator<< ( ostream&os, const MyComplex&c ) { //(F) os << "(" << c.re << "," << c.im << ")" << endl; return os; } int main() { MyComplex first(3, 4); MyComplex second(2, 9); cout << first; // (3, 4) cout << second; // (2, 9) cout << first + second; // (5, 13) cout << first - second; // (1, -5) return 0; }

Comparing the global overload definition for ‘+’ in line (A) of the program in the previous section with the member-function overload definition in line (B) of the above program, note that while the global overload definition has two arguments, the member-function definition has only one. Given two MyComplex objects c1 and c2, a statement such as

      c1 + c2; 

will be translated by the compiler into the following invocation of the operator function for ‘+’:

      c1.operator+( c2 ); 

provided that there exists a member-function overload definition for the function operator+. Such an invocation supplies one argument—c1 here—implicitly and the other argument—c2 here—explicitly to the function operator+. In the member-function definition for operator+, the directly-accessed variables re and im in lines (B) and (C) of the program above are the data members of the implicitly supplied argument c1.

In general, when an operator χ is overloaded with a member-function definition, a construct such as

      object1 χ object2 

is interpreted by the compiler as

      object1.operator χ ( object2 ) 

For this mode of operator use, we can talk about object1 as the invoking object for the operator χ and object2 the argument object. On the other hand, if the operator χ was overloaded with a global definition, the construct

      object1 χ object2 

would be interpreted by the compiler as

      operatorχ ( object1, object2 ) 

Now both object1 and object2 become explicitly-supplied argument objects.

It should now be obvious why the global overload definition for the output operator in line (E) of the program in the previous section cannot be replaced by something like

      ostream&MyComplex::operator<< ( const MyComplex c ) { // WRONG          os << "Real part: " << c.re             << "  Imag part: " << c.im << endl;          return os;      } 

This implementation would be wrong for the simple reason that the manner of usage of the output operator, as in

      cout << expression; 

would be interpreted by the compiler as

      cout.operator <<( expression ); 

if there were a member-function based overload definition available for ‘<<’ for the output stream class basic_ostream of which cout is an object. But we are not at liberty to define new member functions for the output stream classes. Therefore, we have no choice but to use the global overload definition for the output operator. However, we can still can come close to the nature of a member function by declaring the global overload definition for operator<< to be a friend of MyComplex with the following declaration inside MyComplex:

      friend ostream&operator<<( ostream&, const MyComplex&); 

as we have done in line (A) of the program in this section. As mentioned in Chapter 3, the friend declaration, which can be in any of the private, public, or protected sections of a class, allows the global overload definition supplied in line (F) of the program to directly access the private data members of the MyComplex argument object.




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net