Why Does C++ Not Allow Inherited Friendship

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);
}
};

C++ friend inheritance?

Friendship is not inherited in C++.

The standard says (ISO/IEC 14882:2003, section 11.4.8):

Friendship is neither inherited nor transitive.

Is friendship inherited in C++?

In principle, a derived class inherits every member of a base class except:

* its constructor and its destructor
* its operator=() members
* its friends

So, no. Friends are not inherited.

How to propagate friend for derived classes

No, it's deliberately impossibile.

Is an issue by encapsulation.

Suppose to have a class "PswClass" that manage any password, that is cascade friend with other class: if I inherit from PswClass:

 class Myclass : public PswClass {
.......
}

In this way I can, maybe, have access to field that it would be private.

Why are friend functions available for derived classes only when using public inheritance?

As already pointed out in the answer linked above, friendship is not inherited. Thus, a friend of A is not also a friend of B. Having B inherit from A via private access means that all members of A are accessible as private members of B [class.access.base]/1. Since f is not a friend of B, it cannot access private members of B [class.access]/1.1. Since f is not a friend of B, the base class A of B is also not accessible from f [class.access.base]/4. Since the base class A of B is not accessible from f, there's also no way you could get to the A subobject of a B (of which you could access the members) in f [class.access.base]/5…

Why C++ requires public inheritance, ignoring friend declarations, to make dynamic downcast working?

Summarizing the useful infos and cited resources in the comments, a self-answer can be written.

First, the friend declaration is a no-issue: friend affects only the accessibility of the members of the class where it is declared on, but not its base class(es).

Second, accessibility check in C++ goes in compilation time. But the accessibility check of dynamic_cast happens in runtime. This accessibility check is far more restrictive, and the dynamic_cast can happen only if the inheritance is public.

Its likely reason is that doing it correctly would probably require different rtti tables for the different access levels.

Inheriting friendship in C++?

The use of a key is a possible solution.

The idea is that you can unlock the operations only if you have a key... but an example is worth thousands on word so let's dive:

// Step 1: The key
class NeedAccess;

namespace details { class Key { friend NeedAccess; Key() {} }; }

// Step 2: NeedAccess
class NeedAccess
{
protected:
static details::Key GetKey() { return details::Key(); }
};

// Step 3: The big one
class BigOne
{
public:
void lockedMethod(details::Key);
};

The matter of key being copy constructable is up to discussion. I don't see what you can gain by preventing it.

Another benefit is that you can have several keys, depending on which method you want to access, this way you grant 'partial' friendship, and your 'partial' friends can't mess around with your private parts, despite the famous claim!

EDIT:

This method is called Limited Friendship, and was discussed on comp.lang.c++.moderated.

The main advantage of this method in comparison to Private Interface, is the loose coupling, since only forward declarations are necessary.

How does friendship work for derived classes?

Friendship is not inherited. If you want B_Impl to be a friend of A you must declare B_Impl as a friend.

Friendship is also not transitive: your friend's friend is not necessarily your friend.

friend class with inheritance

friendship is neither inherited nor transitive. It is strictly one-one relationship between two classes.

class A {
friend class B;
int Aries;
};

class B {
friend class C;
int Taurus;
};

class C {
int Leo;
void Capricorn() {
A a;
a.Aries = 0; // this wont work, C is not a friend of A.
// friendship is not transitive
}
};

class D : public C {
void Gemini() {
B b;
b.Taurus = 0; // this wont work, D is not a friend of B.
// friendship is not inherited
}
};

class E : public B {
void Scorpio() {
C c;
c.Leo = 0; // this wont work either, friendship is not inherited
}
};

Reference: "The C++ Programming Language" Bjarne Stroustrup

More explanation (mine): If friendship were not one-one, it would be the end of encapsulation. Note that B class can access private members of A only if the class declaration of A declares B as friend. B cannot enforce friendship on A.

Now, if friendship could be inherited, then someone just needs to inherit B to access private members of A, without A having any say in preventing it. Also, allowing friendship to be transitive would lead to other problems, since now B could have a friend C, who in turn could have a friend D, all the way to Z. All of B, C, D, ..., Z can now access A's private members, which would be a disaster.



Related Topics



Leave a reply



Submit