Why does C++ not allow inherited friendship?
Because I may write Foo
and its friend Bar
(thus there is a trust relationship).
But do I trust the people who write classes that are derived from Bar
?
Not really. So they should not inherit friendship.
Any change in the internal representation of a class will require a modification to anything that is dependent on that representation. Thus all members of a class and also all friends of the class will require modification.
Therefore if the internal representation of Foo
is modified then Bar
must also be modified (because friendship tightly binds Bar
to Foo
). If friendship was inherited then all class derived from Bar
would also be tightly bound to Foo
and thus require modification if Foo
's internal representation is changed. But I have no knowledge of derived types (nor should I. They may even be developed by different companies etc). Thus I would be unable to change Foo
as doing so would introduce breaking changes into the code base (as I could not modify all class derived from Bar
).
Thus if friendship was inherited you are inadvertently introducing a restriction on the ability to modify a class. This is undesirable as you basically render useless the concept of a public API.
Note: A child of Bar
can access Foo
by using Bar
, just make the method in Bar
protected. Then the child of Bar
can access a Foo
by calling through its parent class.
Is this what you want?
class A
{
int x;
friend class B;
};
class B
{
protected:
// Now children of B can access foo
void foo(A& a, int n) { a.x = n; }
};
class D : public B
{
public:
foo(A& a, int n)
{
B::foo(a, n + 5);
}
};
A friended class may expose its friend through accessor functions, and then grant access through those.
class stingy {
int pennies;
friend class hot_girl;
};
class hot_girl {
public:
stingy *bf;
int &get_cash( stingy &x = *bf ) { return x.pennies; }
};
class moocher {
public: // moocher can access stingy's pennies despite not being a friend
int &get_cash( hot_girl &x ) { return x.get_cash(); }
};
This allows finer control than optional transitivity. For example, get_cash
may be protected
or may enforce a protocol of runtime-limited access.