Friend functions are not considered class members; they are normal external functions that are given special access privileges. Friends are not in the class’s scope, and they are not called using the member-selection operators (. and –>) unless they are members of another class. The following example shows a Point
class and an overloaded operator, operator+
. (This example primarily illustrates friends, not overloaded operators. For more information about overloaded operators, see Overloaded Operators in Chapter 12.)
#include <iostream.h>
// Declare class Point.
class Point
{
public:
// Constructors
Point() { _x = _y = 0; }
Point( unsigned x, unsigned y ) { _x = x; _y = y; }
// Accessors
unsigned x() { return _x; }
unsigned y() { return _y; }
void Print() { cout << "Point(" << _x << ", " << _y << ")"
<< endl; }
// Friend function declarations
friend Point operator+( Point& pt, int nOffset );
friend Point operator+( int nOffset, Point& pt );
private:
unsigned _x;
unsigned _y;
};
// Friend-function definitions
//
// Handle Point + int expression.
Point operator+( Point& pt, int nOffset )
{
Point ptTemp = pt;
// Change private members _x and _y directly.
ptTemp._x += nOffset;
ptTemp._y += nOffset;
return ptTemp;
}
// Handle int + Point expression.
Point operator+( int nOffset, Point& pt )
{
Point ptTemp = pt;
// Change private members _x and _y directly.
ptTemp._x += nOffset;
ptTemp._y += nOffset;
return ptTemp;
}
// Test overloaded operator.
void main()
{
Point pt( 10, 20 );
pt.Print();
pt = pt + 3; // Point + int
pt.Print();
pt = 3 + pt; // int + Point
pt.Print();
}
When the expression pt + 3
is encountered in the main
function, the compiler determines whether an appropriate user-defined operator+
exists. In this case, the function operator+( Point pt, int nOffset )
matches the operands, and a call to the function is issued. In the second case (the expression 3 + pt
), the function operator+( Point pt, int nOffset )
matches the supplied operands. Therefore, supplying these two forms of operator+
preserves the commutative properties of the +
operator.
A user-defined operator+
can be written as a member function, but it takes only one explicit argument: the value to be added to the object. As a result, the commutative properties of addition cannot be correctly implemented with member functions; they must use friend functions instead.
Notice that both versions of the overloaded operator+
function are declared as friends in class Point
. Both declarations are necessary — when friend declarations name overloaded functions or operators, only the particular functions specified by the argument types become friends. Suppose a third operator+
function were declared as follows:
Point &operator+( Point &pt, Point &pt );
The operator+
function in the preceding example is not a friend of class Point
, simply because it has the same name as two other functions that are declared as friends.
Because friend declarations are unaffected by access specifiers, they can be declared in any section of the class declaration.