Verwenden von "Freund" -Klassen in der Spieleentwicklung

9

In der Regel wird bei der Entwicklung von C ++ - Spielen die Geschwindigkeit gegenüber der Kapselung bewertet. Daher sehen Sie eine Menge öffentlich zugänglicher Klassenmitglieder, die eigentlich nicht öffentlich sein sollten.

Ich scheine in den meisten Fällen festzustellen, dass nur sehr wenige Klassen das Innenleben einer anderen Klasse wirklich kennen müssen, um ihre privaten Daten zu ändern oder zu lesen.

Das Erstellen öffentlicher Getter / Setter für diese privaten Daten enthüllt Dinge, die wirklich nicht ohne weiteres geändert werden sollten.

Wäre es hier ein Kompromiss, Freundesklassen zu verwenden? oder gibt es einen Nachteil bei Freundklassen, die ich nicht sehe?

David Young
quelle

Antworten:

8

Freundschaftsklassen haben zwei Hauptnachteile.

  1. Sie können nicht auswählen, was Sie Ihren Freunden zeigen möchten. Alles oder Nichts. Dies kann sich als problematisch erweisen, wenn Sie versuchen, die obligatorische Verwendung eines nicht inkonsequenten Setzers durchzusetzen.
  2. Ihre beiden Klassen sind jetzt in dem Sinne etwas gekoppelt, dass der Freund über den Freund Bescheid weiß.

Abgesehen davon kann die Verwendung von Freundesklassen die Kapselung definitiv verbessern, insbesondere wenn die Alternative öffentliche Getter / Setter sind.

Verwandte Fragen zu SO: /programming/521754/when-to-use-friend-class-in-c

Tetrad
quelle
5

Verkapselung ist schön, aber die Trennung von Bedenken ist schöner.

Eine Klasse, die auf "einen privaten Teil" einer anderen Klasse zugreift, könnte darauf hinweisen, dass der Code überhaupt nicht gut gestaltet ist.

Jedes Mal, wenn Sie sich in der Stelle "Meine Güte, ich muss hier einen Freund unterrichten" befinden, sollten Sie sich die Frage stellen: "Mache ich das richtig oder gibt es einen saubereren Weg?" (aka "Wird mich das später in den Arsch beißen?").

Wenn Sie sich über die "Freundlichkeit" sicher sind, legen Sie sie ohne zu zögern dort ab.

Egarcia
quelle
Ich verstehe, wie die Verwendung einer Freundesklasse eine Klasse eng mit einer anderen koppelt. Ich habe mich gefragt, ob es insbesondere ein Entwurfsmuster gibt, das das Problem lindert, da es möglicherweise eine schlechtere Lösung ist, nur etwas in einen Getter / Setter zu wickeln.
David Young
1
Interessantes Beispiel ist, dass das Factory-Muster in C ++ aufgrund der Verwendung privater Konstruktoren "friend" erfordert.
David Young
2

Eine andere Option ist die Verwendung des PIMPL-Idioms , wobei ein Teil der Strukturimplementierung ein Zeiger auf einen anderen Typ ist. Die meisten Benutzer der Klasse enthalten nur die normale Header-Datei, wobei die Implementierung ein undurchsichtiger Zeiger ist. Klassen, die Zugriff auf die privaten Daten benötigen, können den Header enthalten, der den anderen Typ definiert, und die bereitgestellte Schnittstelle verwenden.

Dies ist ein gängiges Muster für C-Programmierer, die eine freundschaftliche Funktionalität wünschen. Meiner Meinung nach geht es auch eher darum, über die Trennung von Bedenken (ein allgemein gutes Entwurfsprinzip, das zu wiederverwendbarem, orthogonalem Code führt) als über die Kapselung (eine OO-spezifische Technik, die zur Implementierung der Trennung von Bedenken nützlich ist, aber auch häufig missbraucht wird) nachzudenken Dinge zu komplizieren).

Es hat gegenüber Freunden einen Vorteil, dass es den Freund überhaupt nicht mit dem Freund koppelt. Einige Leute könnten behaupten, dass dies ein Nachteil ist, da jetzt jeder Ihre Klasse "befreundet" haben kann. Ich denke, das ist eine ungerechtfertigte Angst, da Sie die Beziehung immer noch explizit machen (indem Sie den Header einfügen). Wenn Sie Angst davor haben, haben Sie Angst vor Ihrer (oder der Ihrer Mitarbeiter) Fähigkeit, kluge Architekturentscheidungen zu treffen. Aber wenn Sie diese Entscheidungen später nicht richtig treffen können, warum vertrauen Sie sich friendjetzt an?

Es hat einen Nachteil der Laufzeitkosten. Wenn Sie die Daten in einem Zeiger speichern, haben Sie eine schlechtere Cache-Kohärenz und mehr Zuordnungszahlen. Außerdem benötigen Sie einen Destruktor, um sie zu bereinigen.


quelle
+1 interessant, habe noch nie von diesem Konzept mit Java-Hintergrund gehört.
David Young