Warum ist Freundschaft in C ++ nicht zumindest optional vererbbar? Ich verstehe, dass Transitivität und Reflexivität aus offensichtlichen Gründen verboten sind (ich sage dies nur, um einfache Antworten auf häufig gestellte Fragen zu vermeiden), aber das Fehlen von etwas in der Art von virtual friend class Foo;
Rätseln verwirrt mich. Kennt jemand den historischen Hintergrund dieser Entscheidung? War Freundschaft wirklich nur ein begrenzter Hack, der seitdem seinen Weg in ein paar obskure, respektable Zwecke gefunden hat?
Zur Verdeutlichung bearbeiten: Ich spreche über das folgende Szenario, nicht wenn Kinder von A entweder B oder sowohl B als auch seinen Kindern ausgesetzt sind. Ich kann mir auch vorstellen, optional Zugriff auf Überschreibungen von Freundfunktionen usw. zu gewähren.
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. */ };
Akzeptierte Antwort: Wie Loki feststellt, kann der Effekt mehr oder weniger simuliert werden, indem geschützte Proxy-Funktionen in befreundeten Basisklassen ausgeführt werden. Daher besteht keine strikte Notwendigkeit , einer Klassen- oder virtuellen Methodenerbschaft Freundschaft zu gewähren. Ich mag die Notwendigkeit von Boilerplate-Proxys (die die befreundete Basis effektiv wird) nicht, aber ich nehme an, dass dies einem Sprachmechanismus vorzuziehen war, der mit größerer Wahrscheinlichkeit die meiste Zeit missbraucht wird. Ich denke, es ist wahrscheinlich an der Zeit, Stroupstrups The Design and Evolution of C ++ zu kaufen und zu lesen , das ich hier genug empfohlen habe, um einen besseren Einblick in diese Art von Fragen zu erhalten ...
Ich denke, die Antwort auf Ihre erste Frage lautet: "Haben die Freunde Ihres Vaters Zugang zu Ihren Privaten?"
quelle
Eine befreundete Klasse kann ihren Freund durch Accessor-Funktionen entlarven und dann über diese Zugriff gewähren.
Dies ermöglicht eine feinere Steuerung als die optionale Transitivität. Zum Beispiel
get_cash
kannprotected
oder kann ein Protokoll der Laufzeit begrenzten Zugangs erzwingen.quelle
;)
C ++ Standard, Abschnitt 11.4 / 8
Wenn Freundschaft vererbt würde, hätte eine Klasse, die nicht als Freund gedacht war, plötzlich Zugriff auf Ihre Klasseninternalen und dies verstößt gegen die Kapselung.
quelle
Weil es einfach unnötig ist.
Die Verwendung des
friend
Schlüsselworts ist selbst verdächtig. In Bezug auf die Kopplung ist es die schlechteste Beziehung (weit vor Vererbung und Zusammensetzung).Jede Änderung an den Interna einer Klasse kann sich auf die Freunde dieser Klasse auswirken. Möchten Sie wirklich eine unbekannte Anzahl von Freunden? Sie könnten sie nicht einmal auflisten, wenn diejenigen, die von ihnen erben, auch Freunde sein könnten, und Sie laufen Gefahr, jedes Mal den Code Ihres Kunden zu brechen. Dies ist sicherlich nicht wünschenswert.
Ich gebe frei zu, dass bei Hausaufgaben- / Haustierprojekten die Abhängigkeit oft eine weit entfernte Überlegung ist. Bei kleinen Projekten spielt es keine Rolle. Sobald jedoch mehrere Personen an demselben Projekt arbeiten und dies zu Zehntausenden von Zeilen wird, müssen Sie die Auswirkungen von Änderungen begrenzen.
Dies bringt eine sehr einfache Regel:
Das Ändern der Interna einer Klasse sollte sich nur auf die Klasse selbst auswirken
Natürlich werden Sie wahrscheinlich seine Freunde betreffen, aber hier gibt es zwei Fälle:
std::ostream& operator<<(...)
hier, die kein Mitglied rein zufällig der Sprachregeln istIch würde die Verwendung der einfachen Methode empfehlen:
Mit diesem einfachen
Key
Muster können Sie einen Freund (in gewisser Weise) deklarieren, ohne ihm tatsächlich Zugriff auf Ihre Interna zu gewähren, und ihn so von Änderungen isolieren. Darüber hinaus kann dieser Freund bei Bedarf seinen Schlüssel an Treuhänder (wie Kinder) verleihen.quelle
Eine Vermutung: Wenn eine Klasse eine andere Klasse / Funktion als Freund deklariert, liegt dies daran, dass diese zweite Entität einen privilegierten Zugriff auf die erste benötigt. Was nützt es, der zweiten Entität privilegierten Zugriff auf eine beliebige Anzahl von Klassen zu gewähren, die von der ersten abgeleitet sind?
quelle
B
dass Zugriff auf alle Klassen haben würde, die vonA
...Eine abgeleitete Klasse kann nur etwas erben, das 'Mitglied' der Basis ist. Eine Freundeserklärung ist kein Mitglied der Freundschaftsklasse.
und weiter
Wie kann der 'Freund', da er überhaupt kein Mitglied der Basisklasse ist, von der abgeleiteten Klasse geerbt werden?
quelle
Die Friend-Funktion in einer Klasse weist der Funktion die Eigenschaft extern zu. dh extern bedeutet, dass die Funktion irgendwo außerhalb der Klasse deklariert und definiert wurde.
Daher bedeutet dies, dass die Freundesfunktion kein Mitglied einer Klasse ist. Mit der Vererbung können Sie also nur die Eigenschaften einer Klasse erben, nicht externe Dinge. Und auch wenn die Vererbung für Friend-Funktionen zulässig ist, erbt eine Klasse von Drittanbietern.
quelle
Freund ist gut in der Vererbung wie Stilschnittstelle für Container Aber für mich, wie das erste sagen, fehlt C ++ die propagierbare Vererbung
Für mich ist das Problem von C ++ das Fehlen einer sehr guten Granularität, um den gesamten Zugriff von überall für irgendetwas zu steuern:
Freund Sache kann Freund Sache werden. *, um allen Kindern von Sache Zugang zu gewähren
Und mehr noch, Freund [benannter Bereich] Sache. *, Um Zugriff für eine genaue zu gewähren, sind in der Container-Klasse über einen speziellen benannten Bereich für den Freund.
Ok, hör auf mit dem Traum. Aber jetzt kennen Sie eine interessante Verwendung von Freund.
In einer anderen Reihenfolge finden Sie auch interessant zu wissen, dass alle Klassen mit sich selbst befreundet sind. Mit anderen Worten, eine Klasseninstanz kann alle
Mitglieder einer anderen Instanz mit demselben Namen ohne Einschränkung aufrufen :
quelle
Einfache Logik: „Ich habe eine Freundin Jane. Nur weil wir gestern Freunde geworden sind, gehören nicht alle ihre Freunde mir. '
Ich muss diese einzelnen Freundschaften noch genehmigen, und das Maß an Vertrauen wäre dementsprechend.
quelle