Reputation: 269
Say I have a class Complex
.
I have seen both
friend ostream& operator<<( ostream& stream, Complex z)
(i.e. friend function)
ostream& operator<<( ostream& stream, Complex z)
(i.e. member function)
used and I struggle to see when I should exclude friend and when including friend is considered important.
My understanding: both the member function and the friend function can access the private members of class Complex
, a friend function can only be defined in the class itself and it also has access to private members (and public too) of other classes, which a member function does not.
An additional question, since ostream& operator<<( ostream& stream, Complex z)
is a member function, why does it not have to be declared in the class itself? I thought all member functions have to be declared in the class?
Upvotes: 1
Views: 879
Reputation: 91
First things first, friend functions are not defined within the class itself. Friend functions are defined like any other function outside a class. Only their declaration is made within the class along with the friend keyword.
I will explain why friend needs to be used in some operator overloading cases in an easy to understand way:
As you already know, when an object invokes its class member function, the function knows what the member variable values are for that object and can automatically work with those variables. You don't have to explicitly include the object as a parameter within the function.
Similarly when you define an operator overloading function as a member function, the function already knows about the object that calls the function. Now lets consider your example:
friend ostream& operator<<( ostream& stream, Complex z)
Consider how you would call this function:
Complex z;
cout << z;
When the compiler sees this expression, it invokes non-member function operator << with the call
operator<<(cout, z)
If you were to declare this function as:
ostream& operator<<( ostream& stream, Complex z)
This is not a member function. A member function would be as follows:
ostream& operator<<(ostream& stream)
Why you ask? Because the function already knows everything about the object calling this function. Therefore it only needs to know about cout.
Remember that operator overloading functions for binary operators can be member functions only when the left operand is an object of the class in which the function is a member. Now consider how you would call this function. Since binary operators overloading requires that left operand be the object of the class in which the function is defined you would have to call this function as follows:
z << cout
This would result in a compiler call such as:
z.operator<<(cout)
However, no C++ programmer is used to statements such as z << cout and such statements will only lead to confusion. Everyone expects cout << z but since you overloaded operator<< as a member function, you will have to make a call like z << cout. Therefore for such operators non-member friend function is preferred. Also remember that there are certain operators like (), [], ->, or any of the assignment operators, which can only be overloaded as member functions.
Hope you understand why friend is used in some cases better now.
With respect to your second question:
An additional question, since ostream& operator<<( ostream& stream, Complex z) is a member function, why does it not have to be declared in the class itself? I thought all member functions have to be declared in the class?
All member functions have to be declared inside a class. You are probably confusing declaration and definition. Definition can be inside or outside a class, but declaration has to be inside a class. And also,
a friend function can only be defined in the class itself and it also has access to private members (and public too) of other classes, which a member function does not.
This is wrong. Both friend functions and non-static member functions of a class have access to the private and public member variables of that class. Only a static member function cannot access non static member variables of a class.
Upvotes: 2
Reputation: 207
1.The friend stream << means that a global stream operator can access to the member of Complex. For the following exmaple, in main(), a globle outStream can access to Complex member directly.
int main(int ac, char** av)
{
Complex complex;
std::cout << complex;
return 0;
}
2.The member function << of Complex means that Complex itself is a stream, it can accept a parameter whose type is Complex. For following example:
int main(int ac, char** av)
{
Complex comp1, comp2;
comp1 << comp2;
return 0;
}
Even thogh the usage is weired, it is gramatically right.
Upvotes: 0
Reputation: 38267
You can implement the operator overload in both ways, and if you don't need to invoke it with implicit conversion to a Complex
type, you can go with a member function. But there are drawbacks, and providing it via a free function, friend
if access to private members is needed, has become the standard way. The best reference here is Scott Meyer's article on how free functions improve encapsulation. His advice on member vs. non-member function explicitly includes operator <<
:
if (f needs to be virtual) make f a member function of C; else if (f is operator>> or operator<<) { make f a non-member function; if (f needs access to non-public members of C) make f a friend of C; } else if (f needs type conversions on its left-most argument) { make f a non-member function; if (f needs access to non-public members of C) make f a friend of C; } else if (f can be implemented via C's public interface) make f a non-member function; else make f a member function of C;
Upvotes: 3
Reputation: 19607
Firstly,
since
ostream& operator<<( ostream& stream, Complex z)
is a member function, why does it not have to be declared in the class itself?
because it is not a member function. Neither is a function declared with a friend
keyword inside a class.
a friend function can only be defined in the class itself and it also has access to private members (and public too) of other classes, which a member function does not
Member functions are in no way inferior to non-member functions in terms of access rights. The opposite is true - for example, a member function can access private members of its class' friends, non-member (even friend
) functions do not.
To your original question: you use friend
if you need it, because of what it does. Nothing else.
Upvotes: 2