Befreundete Funktionen und Klassen
Wir beschäftigten uns im letzten Kapitel mit der neuen Art, die Standardkanäle zu benutzen. In der Klasse ostream bzw. istream sind für alle vordefinierten Datentypen die entsprechenden Methoden vorhanden. Wollen wir Objekte eigener Klassen ebenfalls mit dem überlagerten <<- Operator ausgeben, ist das mit den bisherigen Mitteln nicht zu schaffen. Eine Methode wird immer nur an den linken Operanden gebunden, der hier ja cout oder cin ist. Die Methode müßte zur entsprechenden E/A-Klasse ostream oder istream gehören. Die E/A-Bibliothek liegt nicht als Quellcode vor. Eine Änderung der E/A-Bibliothek ist nicht damit möglich. Die Methoden scheiden somit aus.
Eine normale Funktion können wir auch nicht verwenden, da zumindest auf die Eigenschaften des Objektes zugegriffen werden muß, das wir ausgeben wollen. Und normale Funktionen haben keine Zugriffslizenz. Was wir bräuchten, wäre eine normale Funktion, die auf die privaten Elemente des auszugebenden Objektes zugreifen darf und zur Überlagerung von Operatoren genutzt werden kann.
Befreundete Funktionen
Das Problem lösen wir mit so genannten Freund-Funktionen. Einem Freund traut der Ersteller der Klasse. Eine befreundete Funktion ist syntaktisch eine normale Funktion, die jedoch in der Klassendefinition erwähnt wird und damit die Zugriffslizenz auf die privaten Elemente erhält.
Befreundete Funktionen werden innerhalb der Klasse, auf deren privaten Elemente sie zugreifen können sollen, deklariert. Das Schüsselwort friend teilt dem Compiler mit, daß es sich um eine normale Funktion, nicht um eine Methode, handelt. In Funktionen existiert keine Bindung. Wie können also nur auf die Parameter zugreifen, die über die Schnittstelle übergeben werden (und globale Variable). Natürlich können in der Schnittstelle auch mehrere Objekte unterschiedlicher Klassen übergeben werden. In diesem Fall wäre es notwendig, die Deklaration in allen Klassen einzufügen, auf deren private Elemente die Funktion zugreift.
|
Befreundete Funktionen und Klassen Seite 127 |
Für die Ausgabe wollen wir nun eine Freund-Funktion schreiben, die den Operator << überlagert. Der Funktionsname muß daher wieder mit dem Schlüsselwort operator gebildet werden.
Die befreundete Funktion hat einen Parameter mehr, als eine entsprechende Methode, da ja die automatische Bindung an das Objekt fehlt. Beachten Sie, daß das Ausgabeobjekt mit übergeben werden muß. Es gibt ja unterschiedliche Ausgabeobjekte. Vordefiniert sind "cout" und cerr. Für Dateien werden wir eigene E/A-Objekte definieren können.
Der Compiler sucht bei der Bearbeitung des Operatorsymbols << nach einer passenden Bearbeitungsfunktion. Entweder ist das eine Methode der Klasse, zu der das links stehende Objekt gehört oder es ist eine Funktion, die die passenden Parameter in der Schnittstelle erwartet.
Diese Funktion muß nicht unbedingt eine befreundete Funktion sein. Da wir aber ein Objekt der Klasse ratio ausgeben wollen, müssen wir auf die privaten Eigenschaften des Objektes zugreifen können. Der Compiler ruft eine überlagerte Funktion wie folgt auf:
|
Seite 128 Einsteigerseminar C++ |
Die neue Ausgabefunktion haben wir nur bei der Klasse ratio als Freund
eingetragen. Bei der Implementierung dürfen wir innerhalb der Funktion
auf die privaten Eigenschaften des übergebenen ratio-Objektes zugreifen,
aber nicht auf die Eigenschaften des ostream-Objektes. Das ist auch nicht
notwendig, da die Eigenschaften der Klasse ratio ausschließlich aus vordefinierten
Datentypen bestehen. Die Ausgabe eines Objektes der Klasse ratio führen
wir in der überlagerten Funktion zurück auf die Ausgabe der Eigenschaften
mit bekannten Datentypen.
Genau wie die Methode muß die überlagerte Funktion einen Rückgabewert bereitstellen, um eine Kettenoperation möglich zu machen. Das zurückgegebene Objekt ist das Ausgabeobjekt. Die Parameter können alle per Referenz übergeben werden. Der Rückgabewert verwendet ebenfalls eine Referenz, da es sich nicht eine Variable mit einer auf die Funktion begrenzte Lebensdauer handelt.
Beachten Sie, daß das Schlüsselwort friend nur bei der Deklaration in der Klasse (Bild 9-1) zur Unterscheidung notwendig war. Wenn wir die Funktion schreiben, ist es nicht erlaubt (Bild 9-3).
|
Befreundete Funktionen und Klassen Seite 129 |
|
Seite 130 Einsteigerseminar C++ |
Die Verwendung im Hauptprogramm (Bild 9-4) unterscheidet sich nicht von der Verwendung des <<-Operators mit überlagerten Methoden. Beachten Sie besonders die Zeile 18, in der gemischt normale Variable und ein ratio-Objekt ausgegeben werden.
Neben einzelnen Funktionen können auch ganze Klassen zu Freunden erklärt werden. Damit erhalten alle Funktionen (Methoden und befreundete Funktionen) der anderen Klasse die Erlaubnis, auf die Elemente der Klasse zuzugreifen.
|
Befreundete Funktionen und Klassen Seite 131 |
Drei Arten von Funktionen
Mit den befreundeten Funktionen haben wir die dritte und letzte Unterprogrammart in C++ kennen gelernt. Fassen wir noch einmal zusammen.
In C++ gibt es drei Arten von Funktionen:
Hinweise zur Weiterarbeit
Schreiben Sie eine Methode, die als Parameter sowohl ein Objekt der Klasse Zeile als auch ein Objekt der Klasse ratio erhält. Die Methode soll den Wert der Bruchzahl zusammen mit einem Führungstext ausgeben. Deklarieren Sie die Methode in einer Klasse und deklarieren Sie sie in der anderen als "friend".
Im nächsten Kapitel
Mit diesem Kapitel haben wir die ersten beiden Grundelemente der Objekt- orientierten Programmierung mit C++ besprochen. Die Klassen dienten dem Schutz vor unerlaubter Veränderung von Daten und die natürliche Programmierung wurde durch die Möglichkeit der Überlagerung von Operatoren unterstützt. Im folgenden Kapitel diskutieren wir einige Möglichkeiten der Optimierung im Umgang mit Klassen.
|
Seite 132 Einsteigerseminar C++ |