Friends in C++

Rishabh Agarwal
4 min readJun 8, 2023

--

Photo by Hannah Rodrigo on Unsplash

Friends in C++ are a way of breaking the encapsulation that classes provides. To use a real-life analogy, friends are like trusted acquaintances who are given access to your private information unlike strangers.

Let us consider a simple example…

Take the following definition of a class named MyClass.

class MyClass {
int value;
public:
MyClass(int value) : value(value) {}
};

If we were to attempt writing a global display function for objects of this class, we would do something like the following.

// INCORRECT : Will Cause Compilation Failure
void display(MyClass& myClass) {
// ERROR: myClass.value is private in MyClass!
std :: cout << myClass.value << std :: endl;
}

But, as we are aware, the compilation for this function will fail because it tries to access private members of the MyClass class and since the display function is a non-member it can not do that.

Can we get our display function to work? Let us try to find a solution…

Approach 1: Why not mark the private data member value public? In this way, display method can easily access this data member.

Problem with Approach 1: Marking value public would loosen the encapsulation not only for display method but for all the other methods as well. This would not be a good approach and could lead to poor design.

Approach 2: So, if we can’t mark the value data member public, why not make display method a member of the MyClass?

Problem with Approach 2: The actual implementation of the display method depends on the use case and it might not be possible to cover all the different implementations in the class definition itself. It is better to leave implementation of display method to the user itself.

None of the standard approach seems to be solving our use case. The next question that we should be asking ourselves is — “Is there a way to selectively break the encapsulation for just the display method?”. The answer amazingly is a big YESSS.

As always… Friends to our rescue

A class in C++ can mark other functions and classes as friends. These functions and classes can then access private (along with public) members of the class where they are marked as friends. And this is how we selectively loosens the encapsulation.

Thus, to get our example working, we can mark the global display function as a friend of the class MyClass. Here is the updated class definition.

class MyClass {
int value;
public:
MyClass(int value) : value(value) {}
friend void display(MyClass& myClass); // display method marked friend
};

With this small change, the display method can now access the private members of the MyClass class. Isn’t it smooth? 🤯

Functions marked with the keyword friend are known as friend functions. Let us try to formally understand them.

Friend Functions

A friend function to a class has the following properties —

  • It has access to private and protected members of a class
  • Should have its prototype included within the class scope with the keyword friend.
  • It is not called with an invoking object of the class.
  • A friend function can be declared friend in multiple classes.

Also, a friend function can be —

  • Any global function
  • A member function of another class
  • A function template

Friend Classes

A friend class of a class —

  • has access to private and protected members of the class in addition to the public members
  • does not have its name qualified with the class scope
  • can be declared friend in more than one class

Also, a friend class can be —

  • A class
  • A class template

We use the following syntax for marking another class (say OtherClass) as friend in our class.

class MyClass {
...
friend class OtherClass;
...
};

Properties of Friend(ship)

Following are some of the properties of friend in C++ —

Friendship is neither commutative nor transitive.

[Commutativity] A is a friend of B, does not imply that B is a friend of A.

[Transitivity] Also, A being a friend of B and B being a friend of C does not imply that A is a friend of C.

This brings us to the end of yet another article on C++. Congratulations on reaching the end, I hoped you learned something new today.

If you want to continue reading, you can check out following similar blogs -

  1. Copying in C++
  2. Access Specifiers in C++
  3. Constant Variables in C++
  4. Classes in C++
  5. Static Members in C++

You can also check out the full series here.

At last, if you enjoy my work then show some appreciation by leaving some claps. You can also subscribe to my newsletter to not miss out on future articles.

--

--

Rishabh Agarwal

Software Developer 2 @ Schrödinger | IIT CSE Graduate - Writes about Software Engineering!