Pourquoi l'amitié n'est-elle pas au moins éventuellement héritable en C ++? Je comprends que la transitivité et la réflexivité sont interdites pour des raisons évidentes (je dis cela uniquement pour éviter les réponses simples de citation de FAQ), mais l'absence de quelque chose du virtual friend class Foo;
genre me laisse perplexe. Quelqu'un connaît-il le contexte historique derrière cette décision? L'amitié était-elle vraiment juste un hack limité qui a depuis trouvé sa place dans quelques utilisations respectables obscures?
Modifier pour clarification: je parle du scénario suivant, pas où les enfants de A sont exposés à B ou à la fois à B et à ses enfants. Je peux également imaginer accorder éventuellement l'accès aux remplacements de fonctions d'amis, etc.
class A {
int x;
friend class B;
};
class B {
// OK as per friend declaration above.
void foo(A& a, int n) { a.x = n; }
};
class D : public B { /* can't get in A w/o 'friend class D' declaration. */ };
Réponse acceptée: comme le déclare Loki , l'effet peut être simulé plus ou moins en créant des fonctions proxy protégées dans des classes de base amies, il n'est donc pas nécessaire d'accorder une amitié à une classe ou à une méthode virtuelle. Je n'aime pas le besoin de procurations standard (ce que la base amie devient effectivement), mais je suppose que cela a été jugé préférable à un mécanisme de langage qui serait plus probablement mal utilisé la plupart du temps. Je pense qu'il est probablement temps d'acheter et de lire The Design and Evolution of C ++ de Stroupstrup , que j'ai vu assez de gens ici recommander, pour mieux comprendre ce type de questions ...
Je pense que la réponse à votre première question se trouve dans cette question: "Les amis de votre père ont-ils accès à vos particuliers?"
la source
Une classe amie peut exposer son ami via les fonctions d'accesseur, puis lui accorder l'accès.
Cela permet un contrôle plus fin que la transitivité facultative. Par exemple,
get_cash
peut êtreprotected
ou peut appliquer un protocole d'accès limité à l'exécution.la source
;)
Norme C ++, section 11.4 / 8
Si l'amitié était héritée, alors une classe qui n'était pas censée être un ami aurait soudainement accès à vos internes de classe et qui viole l'encapsulation.
la source
Parce que c'est simplement inutile.
L'utilisation du
friend
mot-clé est en soi suspecte. En terme de couplage, c'est la pire des relations (bien avant l'héritage et la composition).Tout changement dans les éléments internes d'une classe risque d'avoir un impact sur les amis de cette classe ... voulez-vous vraiment un nombre inconnu d'amis? Vous ne seriez même pas en mesure de les lister si ceux qui en héritent pouvaient aussi être des amis, et vous courriez le risque de casser le code de vos clients à chaque fois, ce n'est certainement pas souhaitable.
J'avoue volontiers que pour les devoirs / projets pour animaux de compagnie, la dépendance est souvent une considération lointaine. Sur les projets de petite taille, cela n'a pas d'importance. Mais dès que plusieurs personnes travaillent sur le même projet et que cela devient des dizaines de milliers de lignes, il faut limiter l'impact des changements.
Cela apporte une règle très simple:
La modification des éléments internes d'une classe ne devrait affecter que la classe elle-même
Bien sûr, vous affecterez probablement ses amis, mais il y a deux cas ici:
std::ostream& operator<<(...)
ici, qui n'est pas membre purement par accident des règles de langueJe recommanderais l'utilisation de la méthode simple:
Ce
Key
modèle simple vous permet de déclarer un ami (d'une certaine manière) sans lui donner réellement accès à vos internes, l'isolant ainsi des changements. De plus, il permet à cet ami de prêter sa clé aux fiduciaires (comme les enfants) si nécessaire.la source
Une supposition: si une classe déclare une autre classe / fonction comme ami, c'est parce que cette deuxième entité a besoin d'un accès privilégié à la première. Quelle est l'utilité d'accorder à la deuxième entité un accès privilégié à un nombre arbitraire de classes dérivées de la première?
la source
B
auriez accès à toutes les classes héritées deA
...Une classe dérivée ne peut hériter que de quelque chose, qui est «membre» de la base. Une déclaration d'ami ne fait pas partie de la classe des liens d'amitié.
et plus loin
Puisque l '«ami» n'est pas membre de la classe de base en premier lieu, comment peut-il être hérité par la classe dérivée?
la source
La fonction Friend dans une classe affecte la propriété extern à la fonction. ie extern signifie que la fonction a été déclarée et définie quelque part hors de la classe.
Cela signifie donc que la fonction friend n'est pas membre d'une classe. L'héritage ne vous permet donc d'hériter que des propriétés d'une classe et non des choses externes. Et aussi si l'héritage est autorisé pour les fonctions d'ami, alors une classe tierce hérite.
la source
Friend est bon en héritage comme l'interface de style pour le conteneur Mais pour moi, comme le premier dit, C ++ manque d'héritage propageable
Pour moi, le problème du C ++ est le manque de très bonne granularité pour contrôler tous les accès de n'importe où pour n'importe quoi:
ami Thing peut devenir ami Thing. * pour accorder l'accès à tous les enfants de Thing
Et de plus, ami [zone nommée] Chose. * Pour accorder l'accès pour un précis sont dans la classe Conteneur via une zone nommée spéciale pour l'ami.
Ok arrête le rêve. Mais maintenant, vous connaissez une utilisation intéressante de l'ami.
Dans un autre ordre, vous pouvez également trouver intéressant de savoir que toutes les classes sont amicales avec soi-même. En d'autres termes, une instance de classe peut appeler tous les
membres d'une autre instance du même nom sans restriction:
la source
Logique simple: «J'ai une amie Jane. Ce n'est pas parce que nous sommes devenus amis hier que tous ses amis sont miens.
Je dois encore approuver ces amitiés individuelles, et le niveau de confiance serait en conséquence.
la source