Operator Overloading Using a Friend Function. McGraw-Hill The Complete Reference Fourth Edition
ಜಾಹಿರಾತು
ಜಾಹಿರಾತು
C h a p t e r 1 5 : O p e r a t o r O v e r l o a d i n g
391 operator (described later), operator functions cannot have default arguments. Finally, these operators cannot be overloaded:
. : : .* ?
As stated, technically you are free to perform any activity inside an operator function. For example, if you want to overload the + operator in such a way that it writes I like C++ 10 times to a disk file, you can do so. However, when you stray significantly from the normal meaning of an operator, you run the risk of dangerously destructuring your program. When someone reading your program sees a statement like Ob1+Ob2, he or she expects something resembling addition to be taking place— not a disk access, for example. Therefore, before decoupling an overloaded operator from its normal meaning, be sure that you have sufficient reason to do so. One good example where decoupling is successful is found in the way C++ overloads the << and
>>
operators for I/O. Although the I/O operations have no relationship to bit shifting, these operators provide a visual "clue" as to their meaning relative to both I/O and bit shifting, and this decoupling works. In general, however, it is best to stay within the context of the expected meaning of an operator when overloading it.
Except for the = operator, operator functions are inherited by a derived class.
However, a derived class is free to overload any operator (including those overloaded by the base class) it chooses relative to itself.
Operator Overloading Using a Friend Function
You can overload an operator for a class by using a nonmember function, which is usually a friend of the class. Since a friend function is not a member of the class, it does not have a this pointer. Therefore, an overloaded friend operator function is passed the operands explicitly. This means that a friend function that overloads a binary operator has two parameters, and a friend function that overloads a unary operator has one parameter. When overloading a binary operator using a friend function, the left operand is passed in the first parameter and the right operand is passed in the second parameter.
In this program, the operator+( ) function is made into a friend:
#include <iostream> using namespace std; class loc { int longitude, latitude; public:
392
C + + : T h e C o m p l e t e R e f e r e n c e loc() {} // needed to construct temporaries loc(int lg, int lt) { longitude = lg; latitude = lt;
} void show() { cout << longitude << " "; cout << latitude << "\n";
}
}; friend loc operator+(loc op1, loc op2); // now a friend loc operator-(loc op2); loc operator=(loc op2); loc operator++();
// Now, + is overloaded using friend function.
loc operator+(loc op1, loc op2)
{ loc temp; temp.longitude = op1.longitude + op2.longitude; temp.latitude = op1.latitude + op2.latitude;
} return temp;
// Overload - for loc.
loc loc::operator-(loc op2)
{ loc temp;
// notice order of operands temp.longitude = longitude - op2.longitude; temp.latitude = latitude - op2.latitude;
} return temp;
// Overload assignment for loc.
C h a p t e r 1 5 : O p e r a t o r O v e r l o a d i n g
393 loc loc::operator=(loc op2)
{ longitude = op2.longitude; latitude = op2.latitude;
} return *this; // i.e., return object that generated call
// Overload ++ for loc.
loc loc::operator++()
{ longitude++; latitude++;
} return *this; int main()
{ loc ob1(10, 20), ob2( 5, 30); ob1 = ob1 + ob2; ob1.show();
} return 0;
There are some restrictions that apply to friend operator functions. First, you may not overload the =, ( ), [ ], or –> operators by using a friend function. Second, as explained in the next section, when overloading the increment or decrement operators, you will need to use a reference parameter when using a friend function.
Using a Friend to Overload ++ or – –
If you want to use a friend function to overload the increment or decrement operators, you must pass the operand as a reference parameter. This is because friend functions do not have this pointers. Assuming that you stay true to the original meaning of the
++
and – – operators, these operations imply the modification of the operand they operate upon. However, if you overload these operators by using a friend, then the operand is passed by value as a parameter. This means that a friend operator function has no way to modify the operand. Since the friend operator function is not passed
394
C + + : T h e C o m p l e t e R e f e r e n c e a this pointer to the operand, but rather a copy of the operand, no changes made to that parameter affect the operand that generated the call. However, you can remedy this situation by specifying the parameter to the friend operator function as a reference parameter. This causes any changes made to the parameter inside the function to affect the operand that generated the call. For example, this program uses friend functions to overload the prefix versions of ++ and – – operators relative to the loc class:
#include <iostream> using namespace std; class loc { int longitude, latitude; public: loc() {} loc(int lg, int lt) { longitude = lg; latitude = lt;
} void show() { cout << longitude << " "; cout << latitude << "\n";
} loc operator=(loc op2); friend loc operator++(loc &op);
}; friend loc operator--(loc &op);
// Overload assignment for loc.
loc loc::operator=(loc op2)
{ longitude = op2.longitude; latitude = op2.latitude;
} return *this; // i.e., return object that generated call
// Now a friend; use a reference parameter.
loc operator++(loc &op)
{
C h a p t e r 1 5 : O p e r a t o r O v e r l o a d i n g
395 op.longitude++; op.latitude++;
} return op;
// Make op-- a friend; use reference.
loc operator--(loc &op)
{ op.longitude--; op.latitude--;
} return op; int main()
{ loc ob1(10, 20), ob2; ob1.show();
++ob1; ob1.show(); // displays 11 21 ob2 = ++ob1; ob2.show(); // displays 12 22
--ob2; ob2.show(); // displays 11 21
} return 0;
If you want to overload the postfix versions of the increment and decrement operators using a friend, simply specify a second, dummy integer parameter. For example, this shows the prototype for the friend, postfix version of the increment operator relative to loc.
// friend, postfix version of ++ friend loc operator++(loc &op, int x);
396
C + + : T h e C o m p l e t e R e f e r e n c e
Friend Operator Functions Add Flexibility
In many cases, whether you overload an operator by using a friend or a member function makes no functional difference. In those cases, it is usually best to overload by using member functions. However, there is one situation in which overloading by using a friend increases the flexibility of an overloaded operator. Let's examine this case now.
As you know, when you overload a binary operator by using a member function, the object on the left side of the operator generates the call to the operator function.
Further, a pointer to that object is passed in the this pointer. Now, assume some class that defines a member operator+( ) function that adds an object of the class to an integer. Given an object of that class called Ob, the following expression is valid:
Ob + 100 // valid
In this case, Ob generates the call to the overloaded + function, and the addition is performed. But what happens if the expression is written like this?
100 + Ob // invalid
In this case, it is the integer that appears on the left. Since an integer is a built-in type, no operation between an integer and an object of Ob's type is defined. Therefore, the compiler will not compile this expression. As you can imagine, in some applications, having to always position the object on the left could be a significant burden and cause of frustration.
The solution to the preceding problem is to overload addition using a friend, not a member, function. When this is done, both arguments are explicitly passed to the operator function. Therefore, to allow both object+integer and integer+object, simply overload the function twice—one version for each situation. Thus, when you overload an operator by using two friend functions, the object may appear on either the left or right side of the operator.
This program illustrates how friend functions are used to define an operation that involves an object and built-in type:
#include <iostream> using namespace std; class loc { int longitude, latitude; public:
C h a p t e r 1 5 : O p e r a t o r O v e r l o a d i n g
397 loc() {} loc(int lg, int lt) { longitude = lg; latitude = lt;
} void show() { cout << longitude << " "; cout << latitude << "\n";
}
}; friend loc operator+(loc op1, int op2); friend loc operator+(int op1, loc op2);
// + is overloaded for loc + int.
loc operator+(loc op1, int op2)
{ loc temp; temp.longitude = op1.longitude + op2; temp.latitude = op1.latitude + op2; return temp;
}
// + is overloaded for int + loc.
loc operator+(int op1, loc op2)
{ loc temp; temp.longitude = op1 + op2.longitude; temp.latitude = op1 + op2.latitude;
} return temp; int main()
{ loc ob1(10, 20), ob2( 5, 30), ob3(7, 14); ob1.show();
ಡೌನ್ಲೋಡ್ ಮಾಡಿ
ಜಾಹಿರಾತು