Exploring Friend Classes: Benefits & Examples

  • Thread starter ChrisVer
  • Start date
  • Tags
    Classes
In summary: One way to mitigate this is to use a function that is a wrapper for the operators. This way, the function can take any number of arguments, and the compiler can check at compile time that the operator is called exactly once for each argument. This also allows the use of operator overloading, which lets you define a custom operator for any function.Friend classes can help with this, too. Suppose you want to define a function that computes the Frobenius norm of a matrix. You could do this, for example, by defining a class that represents matrices, and then defining a function that takes a matrix as an argument and returns the Frobenius norm of that matrix.In summary,
  • #1
ChrisVer
Gold Member
3,378
464
I know that this might seem a little stupid question, but I'd like to read some answers or maybe see some examples (better put as problems for my own practice)?
I don't understand how the concept of friend classes is useful in programing.
Classes, in my understanding, are supposed to be some kind of structures that allow you to create objects with certain attributes and methods on those objects. The attributes or methods can be private (accessed only from within the class) or public (accessed from outside the class), and recently I came across the protected but I am not sure how it really works yet but this is irrelevant.
Then I learned that friend classes are able to access the private elements of its class.
What is confusing me, is that I don't see the reason of making some elements of a class private if you want to access them in some other part of your code later on. Or define a friend class that you want to enter the private parts of your main class and modify them instead of doing that in your main class (this question may not receive an answer, since it's based on the contradiction arising between the concepts of friendship and encapsulation). Especially if you are building the code, I find the whole concept of friendship irrelevant (since there are ways to avoid it) and the code to be less readable to others (at least I can get confused reading through such a code).
I would appreciate your answers. Also, do you have some examples that can make the concept of friendship clear and necessary? I would appreciate the examples as "problems" (to make me think about it) rather than a copy-paste of some code.
Thanks.
 
Technology news on Phys.org
  • #2
This is a common question. There is no contradiction between the concepts of friendship and encapsulation. https://isocpp.org/wiki/faq/friends#friends-and-encap

Since you ask for an example as a problem to think about: in addition to the points in that FAQ, and the standard example of operator overloading, I invite you to consider using friends for unit testing.
 
  • Like
Likes FactChecker and ChrisVer
  • #3
There are many features that you don't have to use. I don't recall ever having used a friend class or operator overloading. So, I wouldn't worry about it. Just be aware it exists. My guess is that you will never feel a need for them.
 
  • Like
Likes ChrisVer
  • #4
ChrisVer said:
I don't understand how the concept of friend classes is useful in programing.
You didn't mention friend functions. Do you understand how they are useful?

What is confusing me, is that I don't see the reason of making some elements of a class private if you want to access them in some other part of your code later on. Or define a friend class that you want to enter the private parts of your main class and modify them instead of doing that in your main class (this question may not receive an answer, since it's based on the contradiction arising between the concepts of friendship and encapsulation).
Friendship doesn't break encapsulation. It extends it, and under controllable circumstances. As a young adult, you may still have the key to your parent's house, but maybe not to their boat.

To address the latter part of this question, one very common use of friend classes is in classes where all (or almost) all of the work is performed by a private data member of an opaque pointer type:
Code:
// File Foo.hpp

#ifndef FOO_HPP
#define FOO_HPP

// Most of the functionality in class Foo is performed by class FooImplementation.
// All we need here is a forward declaration of that class.
class FooImplementation;

class Foo {
public:
    Foo();
    void do_something();
    void do_something_else(Foo& other);
private:
    friend class FooImplementation;
    FooImplementation* impl;
};

#endif

Code:
// File FooImplementation.hpp

#ifndef FOO_IMPLEMENTATION_HPP
#define FOO_IMPLEMENTATION_HPP

#include "foo.hpp"
#include "foreign/object.hh"

class FooImplementation {
public:
    FooImplementation();
    void do_something();
    void do_something_else(Foo& other);
private:
    foreign::object foreign_object;
};

#endif

Code:
// Foo.cpp

#include "Foo.hpp"
#include "FooImplementation.hpp"

void Foo::do_something() {
    impl->do_something ();
}

void Foo::do_something_else (Foo& other) {
    impl->do_something_else (other);
}

Here, the private implementation walls off the #include "foreign/object.hh" that is needed in the definition of FooImplementation. That external header might in turn #include lots of other files. In modern C++, it's not uncommon to see a short file expand into tens or even hundreds of thousands once the preprocessor is done with that short file. The PIMPL design pattern acts as a compilation firewall that helps prevent the generation of those massive files.Another place where friendship is used widely is in operator overloading. Suppose you want to develop a linear algebra package. Because operators in C++ are boolean (e.g., a+b+c+d is implemented as ((a+b)+c)+d or a+(b+(c+d))), a naive implementation will most likely result in generation of temporaries. This has a number of downsides: Multiple traversals where one would do, and multiple calls to new and delete (which in turn call malloc and free), where only one temporary (or perhaps not even one) is needed. This overhead can be avoided by using expression templates to implement lazy evaluation. Those expression class templates oftentimes need to be friends of the matrix or vector classes so as to ultimately perform the computation.
 
  • Like
Likes Filip Larsen
  • #5
Hornbein said:
or operator overloading
You haven't been programming very long have you? :P

Friend classes are pretty useless if you design your code correctly. Every so often you want a class to be able to manipulate another one's private functions, but it's rare. The only example I can think of is a factory class, often you don't want to be able to use the new operator to create a new instance of a class, so you make all of the ctors private and use a factory class to create them. I usually put the factor method in the same class that it's trying to create, but sometimes I create factories that can return a number of different types of objects.

However, there is one place where it's very very useful.
C:
class foo {
private:
    friend class UnitTest;  //You should certainly be asserting private members in a unit test
};
 
  • #6
newjerseyrunner said:
You haven't been programming very long have you? :P
]

I guess not. Only twenty-five years.

Please do not send me any more insults, if that's not too much to ask.
 
  • #7
Hornbein said:
I guess not. Only twenty-five years.

Please do not send me any more insults, if that's not too much to ask.
I didn't mean to insult, I'm very surprised that someone with your experience have never needed operator overloading. Especially the assignment operator, which is normally coded in tandem with the copy constructor.
 
Last edited:
  • #8
newjerseyrunner said:
The only example I can think of is a factory class ...
You haven't been programming very long have you? :P (Right back at ya!)

Friend classes are pretty useless if you design your code correctly.
Look at Boost and the C++ standard library before you say that. Both use friend classes quite extensively, particularly for the PIMPL idiom. Eigen and BLITZ++ use friend classes, too. Friend classes can be quite useful when used in the right context.

However, there is one place where it's very very useful.
C:
class foo {
private:
    friend class UnitTest;  //You should certainly be asserting private members in a unit test
};
This is one of those religious wars in modern programming. There are many who highly debate that "you should certainly be asserting private members in a unit test". While some say you certainly should unit test protected and private members (in which case you need to break encapsulation), others say you certainly should not.
 
  • #9
newjerseyrunner said:
I didn't mean to insult, I'm very surprised that someone with your experience have never needed operator overloading. Especially the assignment operator, which is normally coded in tandem with the copy constructor.
I doubt @Hornbeim was thinking of the assignment operator when he wrote "I don't recall ever having used a friend class or operator overloading." Properly overloading the assignment operator is basic rule of three stuff (or with c++11 and beyond, rule of five stuff). I suspect he was instead thinking of the other 49 overloadable operators in C++. How many times have you found a need to overload the comma operator?

I've written a few simple classes where I've overloaded operator+ et al, but I'm more likely to be using some carefully designed and very well-tested package that has done all the hard work of making sure that those overloaded arithmetic operators are well-behaved. It's easy to get it wrong and create overloads that behave poorly.
 
  • #10
D H said:
I doubt @Hornbeim was thinking of the assignment operator when he wrote "I don't recall ever having used a friend class or operator overloading." Properly overloading the assignment operator is basic rule of three stuff (or with c++11 and beyond, rule of five stuff). I suspect he was instead thinking of the other 49 overloadable operators in C++. How many times have you found a need to overload the comma operator?

I've written a few simple classes where I've overloaded operator+ et al, but I'm more likely to be using some carefully designed and very well-tested package that has done all the hard work of making sure that those overloaded arithmetic operators are well-behaved. It's easy to get it wrong and create overloads that behave poorly.
True, I've never used the comma operator. +=, ++, ==, =... are very common though, especially if you have containers with iterators.

@ChrisVer As for protected methods, these are the same as private methods, except they are also accessible by child classes. A private member or method is not usable by any object that inherits from your base class, this is useful for hiding weird internals that the child classes should not be interacting with.

D H said:
This is one of those religious wars in modern programming. There are many who highly debate that "you should certainly be asserting private members in a unit test". While some say you certainly should unit test protected and private members (in which case you need to break encapsulation), others say you certainly should not.
I'm actually on the side that unit tests should not be friends with anything, I just mentioned it as a common use. I actually do something completely different (-D private=public at compile time,) but that's equally controversial.
 

1. What is a friend class?

A friend class is a class that has access to the private and protected members of another class. This allows the friend class to manipulate or access data that would otherwise be inaccessible.

2. What are the benefits of using friend classes?

Friend classes can be useful in situations where multiple classes need access to the same private or protected data. It can also help to simplify and organize code by allowing related classes to share data more easily.

3. How do you declare a friend class?

To declare a friend class, the keyword "friend" is used in the class declaration of the class that is being granted access. This means that the friend class will have access to all private and protected members of the declared class.

4. Can a friend class inherit from the declared class?

Yes, a friend class can inherit from the declared class. In this case, the friend class will have access to all private and protected members of the declared class, as well as any inherited members.

5. Are there any potential drawbacks to using friend classes?

One potential drawback of using friend classes is that it can break encapsulation by allowing external classes to access private and protected data. This can make the code more difficult to maintain and debug. It is important to use friend classes carefully and only when necessary.

Similar threads

  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
2
Replies
36
Views
3K
  • Programming and Computer Science
Replies
25
Views
3K
  • Programming and Computer Science
Replies
23
Views
2K
  • Programming and Computer Science
2
Replies
35
Views
2K
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
2
Views
688
  • Programming and Computer Science
Replies
5
Views
818
  • Programming and Computer Science
Replies
25
Views
2K
  • Programming and Computer Science
Replies
5
Views
784
Back
Top