ReviseAlgo Logo

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.