Is there a name for the idiom of using a friend class to hide what would have been private functions?
The Attorney-Client idiom.
Is there any reason not to do it?
As suggested also in some comments, here's a reason not to do it: while it provides a patterned option, it avoids dealing with the root of the problem - the design of the original class (class Foo
).
In your question you write:
If a class has lots of private functions it seems undesirable to have them declared in the header file.
There's some subjectivity to this question so allow me to restate it more objectively with the following question.
Are there ways to avoid private member functions?
You pointed out one way, to use the PIMPL idiom. As also suggested in some comments, here's some more:
- Refactor the original (a.k.a. client) class to instead use non-member non-friend functions or lambda expressions that manipulate your class member data through parameters - so that it doesn't need private member functions.
- Split up the class into multiple smaller classes so that each of the smaller classes declares less of the original class's private member functions. Like with member data, the more private member functions a class has, the more likely - at least in my opinion - the class is violating the single responsibility principal. So this kind of effort can reduce the private member functions as well making your class design more robust.
Say we start with the following code:
//Foo.h
class Foo
{
public:
void FuncA();
void FuncB();
private:
void multiplyByTwo();
int x;
// more data...
};
//Foo.cpp
void Foo::multiplyByTwo()
{
x = x * 2;
}
void Foo::FuncA()
{
multiplyByTwo();
}
Here's an example using the first way of what this could be changed to:
//Foo.h
class Foo
{
public:
void FuncA();
void FuncB();
private:
int x;
// more data...
};
//Foo.cpp
namespace {
int multiplyByTwo(int x)
{
return x * 2;
}
}
void Foo::FuncA()
{
x = multiplyByTwo(x);
}
In addition to eliminating the declaration of multiplyByTwo
as a private member function of class Foo
, this change also more idiomatically expresses the intention of the multiplyByTwo
function in now saying in C++ syntax what's its input and output.