I know that friendship is not inherited. I was asking myself: why? Why the C++ designers decided to not let friendship be inherited? Do you find that friendship inheritance would be a useful thing to have? My own answer is yes: in the same way that B is a friend of A, i would like to make a whole family of classes be friend of A (B and its derivatives). Maybe, one should be able to say: let only B be friend of A or let B and its derived classes be friend of A.
Ps. I don't know why many of you thought that i was asking for automatic extension of f开发者_开发百科riendship. I was interested more in the possibility for the programmer to extend friendship to a whole family using some mechanism (not automatically).
A friend
declaration creates a strong relationship between the Friendly and the Trusting:
- it ties down the Friendly to the representation of the Trusting since it's got full access to its internals
- it means that the Friendly swears to uphold the class invariants of the Trusting
Therefore it seems good practice to make sure to clearly identify the exact scope, something that inheritance would not achieve: there would be a leak.
The truth is though, that inheritance should not even be necessary. There are actually two alternatives, depending on what friendship is trying to achieve. They cover any scenario I ever come across.
Friendly as a Proxy
In your example, derivates of Friendly
can simply reach into Trusting
through Friendly
, thus letting you control the operations that occur on Trusting
in a limited set of places.
class Trusting { friend class Friendly; };
class Friendly { protected: void modifyTrusting(); };
The implementation of modifyTrusting
might imply virtual calls (hooks) to customize the behavior, but regardless of those hooks it is up to Friendly
to ensure that the class invariants are not broken.
Not so Trusting
In this case, Trusting
opens up only part of its interface, through a locked method, and grants the key to Friendly
. Friendly
might alternatively grant the key to the classes in which it trusts, but it does not really matter... In any case Trusting
ensures itself that its invariants are not broken, and the key is just a mechanism to reduce the exposure of the method.
class Key { friend class Friendly; Key() {} ~Key() {} };
class Trusting { public: void doSomething(Key const&); };
class Friendly { protected: Key const& key() const; };
I must admit that I am really partial to this latter method and use it regularly, because it limits the exposure of Friendly
to the implementation details of Trusting
. It also clearly documents which parts of Trusting
our dear Friendly
access.
I saw an amusing bumper sticker yesterday: "My mother-in-law is a travel agent ... for guilt trips". Friendship is inherited to some extent in human relationships. While this does lead to interesting jokes about an SOs friends and family, it is important to remember that misery and suffering are the basis for many jokes.
Friendship is not inherited in C++ because the developers foresaw the amount of misery and suffering this would cause.
This is a terrible idea.
Friendship is not inherited because friendship causes a tight coupling between friends. If all the derived class were also automatically friends then this would cause a tight binding between the original object and all inherited classes.
Tight coupling is fine for classes that are created and maintained together. But for classes that are created by other users tight coupling would cause a maintenance nightmare and prevent you from ever changing the original object (because all your tightly coupled friends depend on your implementation).
精彩评论