A typical use is to grant access to functions that form part of the class' interface, but thanks to other rules can't really be part of the class proper. Inserters/extractors for iostreams are a classic example:
namespace whatever {
class something {
// ...
friend std::ostream &operator<<(std::ostream &os, something const &thing);
friend std::istream &operator>>(std::istream &is, something &thing);
};
}
Making these operators members of the class will not work. An I/O operation looks something like:
whatever::something thing;
std::cout << thing;
For an operator implemented as a member function, this would be resolved as:
std::cout.operator<<(thing);
I.e., the function would have to be a member of std::cout
, not of something
. Since we don't want to modify std::ostream
constantly, our only reasonable option is to overload the operator with a free function instead of a member function. That leaves us with two possibilities: either ignore encapsulation completely, and make everything in the class public, or else keep it private, but grant access to the few things that really need it.
Making another class a friend is rather less common. In this case, you're typically creating something on the order of a module or subsystem -- a set of classes that work together and have some degree of special access to each other that's not granted to the world at large.