Object-Oriented Programming
Friend Functions and Classes
Granting external access to private members when encapsulation needs to be relaxed
Interview: Access control design — when to use friend, operator<< pattern, and why friend is not a design smell when used correctly
Friend Functions and Classes
A friend declaration grants a specific external function or class full access to a class's private and protected members. Friendship is explicitly declared by the class being accessed — it cannot be assumed or inherited. It is a deliberate relaxation of encapsulation for a tightly related function or class that logically needs access.
When to Use Friend
Friend is most commonly used for: (1) overloading operator<< and operator>> for stream I/O — these cannot be class members since the left operand is the stream, not the class; (2) symmetric binary operators (e.g., operator+ that needs access to internals of both operands); (3) closely related classes in a module that share implementation details.
Properties of Friendship
- Not inherited: A derived class does not inherit friendship. A friend of the base class is not a friend of the derived class.
- Not transitive: A friend of a friend is not automatically a friend.
- Not symmetric: If A is a friend of B, B is not automatically a friend of A.
- Declared by the granting class: Only the class being accessed controls who its friends are.
Interview Corner
Q: Why is operator<< typically implemented as a friend function?
A: operator<< has the stream on the left: cout << obj. As a member function, it would need to be a member of ostream (which you can't modify) or of your class with the stream as a parameter, but then the syntax would be obj.operator<<(cout) — wrong order. As a non-member friend function, it has the natural operator<<(ostream&, const T&) signature and can access private members via friendship.
Q: Does friend violate encapsulation?
A: Used judiciously, no. Encapsulation's goal is protecting invariants from arbitrary external modification. Friend functions are explicitly listed by the class — not arbitrary. They're part of the class's interface, just implemented outside. Overusing friend for convenience (avoiding proper getter/setter design) does undermine encapsulation. The key test: is the friend function logically part of the class's behavior?
Common Pitfalls
- Overusing friend: If many functions need friend access, the class's interface design may be wrong. Consider providing well-designed public methods instead.
- Expecting friendship to be inherited: A friend function of Base cannot access private members of Derived — friendship is not inherited.
Best Practices
- Use friend primarily for
operator<<,operator>>, and symmetric comparison operators. - Prefer public accessor methods over friend for general class interactions — reserve friend for operations that genuinely need internal access and are logically part of the class's behavior.