I get quite a few questions about when or whether it’s a good idea to declare friend classes in C++. Here is some background and advice on the use of friend classes.
Recall that members of a class that are defined as private are only accessible by members of the class in which they are defined. They are not visible to anyone outside the class. Likewise, protected members are only accessible by other classes in the same inheritance hierarchy (i.e. classes within in the same “family tree” of descendants), and are not visible outside that family’s class hierarchy.
But there are loopholes in every contract. And sometimes, loopholes can be useful.
What if you needed to provide another class — a highly-trusted class — with full access to your class’s private and protected members? Although this would break the encapsulation rule, it’s a situation that comes up fairly often, especially when a data structure implementation requires more than one class to implement it.
For example, a doubly-linked list data structure might be implemented as two separate classes: the list itself as one class (containing the head and tail pointers, a count of nodes, etc.), and a node on that list as another class (containing data itself, along with pointers to the previous and next nodes). Logically, the member functions used to manage the list (e.g., check for empty, add a node, delete a node, traverse the list, etc.) belong in the list class and not in the node class. And all the link pointers in both classes should be private. In this situation, you would want members of the list class to have full access to the node class, so that its member functions can efficiently manipulate a node’s previous and next pointers.
This is where a friend class enters the picture. A class Z can declare another class Q as a friend. The friend class Q now has full access to all of class Z’s private and protected members. Those members of Z are still invisible outside the Z class, but are visible to and accessible by the friend class Q.
// public members of the Z class
// private members of the Z class
friend class Q; // We allow Q direct access to all of Z's internals.
Keep in mind that class Q can’t just decide on its own that it wants full access to class Z’s internals. If a class could do that, then you would never know what other classes might have access to your internals, and you would end up with an un-encapsulated mess. Class Z must explicitly grant that access to class Q, by explicitly declaring class Q as a friend class. So, a class must explicitly allow another class to be its friend.
Note that the friend declaration is only one way. If Z declares that Q is a friend, as shown above, Q has access to Z’s internals, but Z has no access to Q’s internals. For Z to have access to Q’s internals, the Q class would have had to explicitly declare Z as its friend.
Syntactically, the friend class declaration can be placed anywhere within the class definition. As illustrated in the example above, I recommend placing friend declarations at the end of the class definition, after all the private members. It’s not a piece of information that users of the class really need to know, and it’s a good reminder when you’re looking at the class’s private members that another class has access to those private members.