Friend Functions and Friend Classes


By Alex Allain
It is often useful for one class to see the private variables of another class, even though these variables should probably not be made part of the public interface that the class supports. For instance, if you were writing a binary tree, you might want to use a Node class that has private data, but it would still be convenient for the functions that actually combine nodes together to be able to access the data directly without having to work through the Node interface. At times, it may not even be appropriate for an accessor function to ever give even indirect access to the data.

Friend Classes

C++ provides the friend keyword to do just this. Inside a class, you can indicate that other classes (or simply functions) will have direct access to protected and private members of the class. When granting access to a class, you must specify that the access is granted for a class using the friend keyword:
friend class aClass;
Note that friend declarations can go in either the public, private, or protected section of a class--it doesn't matter where they appear. In particular, specifying a friend in the section marked protected doesn't prevent the friend from also accessing private fields.

Here is a more concrete example of declaring a friend:
class Node 
{
    private: 
    int data;
    int key;
    // ...

    friend class BinaryTree; // class BinaryTree can now access data directly
};
Now, Node does not need to provide any means of accessing the data stored in the tree. The BinaryTree class that will use the data is the only class that will ever need access to the data or key. (The BinaryTree class needs to use the key to order the tree, and it will be the gateway through which other classes can access data stored in any particular node.)

Now in the BinaryTree class, you can treat the key and data fields as though they were public:
class BinaryTree
{
    private:
    Node *root;

    int find(int key);
};
int BinaryTree::find(int key)
{
    // check root for NULL...
    if(root->key == key)
    {
        // no need to go through an accessor function
        return root->data;
    }
    // perform rest of find

Friend Functions

Similarly, a class can grant access to its internal variables on a more selective basis--for instance, restricting access to only a single function. To do so, the entire function signature must be replicated after the friend specifier, including the return type of the function--and, of course, you'll need to give the scope of the function if it's inside another class:
friend return_type class_name::function(args);
For instance, in our example Node class, we would use this syntax:
class Node 
{
    private: 
    int data;
    int key;
    // ...

    friend int BinaryTree::find(); // Only BinaryTree's find function has access
};
Now the find function of BinaryTree could access the internals of the Node class, but no other function in BinaryTree could. (Though we might want a few others to be able to!)

Note that when friends are specified within a class, this does not give the class itself access to the friend function. That function is not within the scope of the class; it's only an indication that the class will grant access to the function.

friend and Encapsulation

Some people believe that the idea of having friend classes violates the principle of encapsulation because it means that one class can get at the internals of another. One way to think about this, however, is that friend is simply part of a class's overall interface that it shows the world. Just like an elevator repairman has access to a different interface than an elevator rider, some classes or functions require expanded access to the internals of another class. Moreover, using friend allows a class to present a more restrictive interface to the outside world by hiding more details than may be needed by anything but the friends of the class.

Finally, friends are particularly common in cases of operator overloading because it is often necessary for an overloaded operator to have access to the internals of the classes that are arguments to the operator.