Weil besser als gut!

Operatorüberladung (C++)Inhaltsverzeichnis Operatorüberladung (operator overloading)Operatoren können überladen werden, allerdings gelten folgende Einschränkungen:
. .* :: ?: Operatoren können generell realisiert werden als:
Die Operatoren = () [] -> können nur als member function realisiert werden. Die Syntax der Operatorfunktionen ist identisch zur Syntax 'normaler' Funktionen, allein der Funktionsbezeichner lautet: operatorop BeispielMöchte man etwa den Operator * überladen, um Objekte der Klasse Mitarbeiter zu multiplizieren: C++ Mitarbeiter operator*( Mitarbeiter links, Mitarbeiter rechts ) { // programmcode... } Der Aufruf dieser Funktion erfolgt alternativ in Funktions- oder Operatorschreibweise (Tom und Jerry seien Objekte der Klasse Mitarbeiter): C++ Tom = operator*(Tom, Jerry); Tom = Tom * Jerry; Hinweis: Natürlich ist es Unsinn, Mitarbeiter zu multiplizieren. Es wird dringend empfohlen, sich nicht zu weit von der ursprünglichen Semantik eines Operators zu entfernen! weitere AufrufvariantenBeim Aufruf ist außerdem relevant, ob es sich um:
Als member function hätte die Multiplikation nur einen Parameter (der andere ist das hidden argument): C++ Mitarbeiter Mitarbeiter::operator*(Mitarbeiter rechts) { // Programmcode... } Aufrufe in Funktions- oder Operatorschreibweise : C++ Tom = Tom.operator*(Jerry); Tom = Tom * Jerry; // unverändert! Aufrufe unärer OperatorenAlle unären Operatoren sind prefix Operatoren, nur ++ und -- gibt es als pre- und postfix Variante. Somit gibt es 4 Möglichkeiten: member function, prefixC++ void Mitarbeiter::operator++( ) { ... } Aufrufe: C++ Tom.operator++(); ++Tom; member function, postfixC++ void Mitarbeiter::operator++( int dummy ) // dummy Argument dient nur zur Unterscheidung von prefix / postfix { // Programmcode ... } Aufrufe: C++ Tom.operator++(42); Tom++; non-member function, prefixC++ void operator++( Mitarbeiter m ) { ... } Aufrufe: C++ operator++(Tom); ++Tom; non-member function, postfixC++ void operator++(Mitarbeiter m, int dummy) // dummy Argument kennzeichnet postfix { // Programmcode ... } Aufrufe: C++ operator++(Tom, 42); Tom++; Bemerkungen zum Beispiel op01.cpp
Typwandlereigene 'Typwandler' können sein:
ErweiterungDas obige Beispiel hat keinen Bezug zur OOP - alle Attribute sind public, eine globale Funktion greift direkt darauf zu. Dies soll nun behoben werden: die Daten werden private und die Operatorfunktion wird member der Klasse, so dass sie Zugriff auf die Daten hat. Test
Schreibt man die beiden Operatoraufrufe in Funktionsschreibweise, wird das Problem klar: C++ x.operator+(1); // o.k., 1 wird mit dem Konstruktor konvertiert 2.operator+(x); // 2: nicht möglich, keine Konvertierung Nicht statische Methoden verhalten sich 'asymmetrisch', da für das hidden argument keine benutzerdefinierten Konvertierungen vorgenommen werden. Anders ausgedrückt: das hidden argument ('this pointer argument') muss immer den Typ Zeiger auf Objekt der eigenen Klasse haben. Will man symmetrisches Verhalten wie in op01 und dennoch auf private Daten nicht verzichten, bleibt nur, einen friend-Operator anzulegen. Anmerkung: Eine weitere (ähnliche) Situation, die einen friend-Operator erfordert, werden wir später beim Überladen von << kennenlernen. Unäre OperatorenDieses Problem tritt bei unären Operatoren nicht auf, sie sollten möglichst immer als member implementiert werden. Ergebnis: Der friend Operator löst das Symmetrieproblem, die Daten können privat deklariert werden Überladung der ZuweisungDie Default-Zuweisung erzeugt keine tiefe Kopie (s. auch copy-Konstruktor, Prog2 - Labor Nr. 4). Durch Überladung des = Operators kann der Mangel jetzt behoben werden: Da als L-value (linker Operand von =) immer nur ein Objekt der eigenen Klasse erlaubt sein soll, tritt das Symmetrieproblem nicht auf. Der Operator kann damit als member implementiert werden:
|
Zahlen & Daten
Publish |