|
||||
|
Section 15:
|
[15.9] But shouldn't I always use a printOn() method rather than a friend function?
No. The usual reason people want to always use a printOn() method rather than a friend function is because they wrongly believe that friends violate encapsulation and/or that friends are evil. These beliefs are naive and wrong: when used properly, friends can actually enhance encapsulation. This is not to say that the printOn() method approach is never useful. For example, it is useful when providing printing for an entire hierarchy of classes. But if you use a printOn() method, it should normally be protected, not public. For completeness, here is "the printOn() method approach." The idea is to have a member function, often called printOn(), that does the actual printing, then have operator<< call that printOn() method. When it is done wrongly, the printOn() method is public so operator<< doesn't have to be a friend — it can be a simple top-level function that is neither a friend nor a member of the class. Here's some sample code:
#include <iostream>
class Fred {
public:
void printOn(std::ostream& o) const;
...
};
// operator<< can be declared as a non-friend [NOT recommended!]
std::ostream& operator<< (std::ostream& o, Fred const& fred);
// The actual printing is done inside the printOn() method [NOT recommended!]
void Fred::printOn(std::ostream& o) const
{
...
}
// operator<< calls printOn() [NOT recommended!]
std::ostream& operator<< (std::ostream& o, Fred const& fred)
{
fred.printOn(o);
return o;
}
People wrongly assume that this reduces maintenance cost "since it avoids
having a friend function." This is a wrong assumption because:
Net: the member-called-by-top-level-function approach has a cost but no benefit. Therefore it is, in general, a bad idea. Note: if the printOn() method is protected or private, the second objection doesn't apply. There are cases when that approach is reasonable, such as when providing printing for an entire hierarchy of classes. Note also that when the printOn() method is non-public, operator<< needs to be a friend. |
|||