zurück weiter

Operatoren überladen
Beispiele

G.Eichelsdörfer
Staatliche Technikerschule Weilburg

Beispiele zum Überladen von Operatoren

Das Überladen von Operatoren ist nur für Operanden möglich bzw. zweckmäßig, die nicht zum C++-Standard gehören. Dazu zählen insbesondere selbst definierte Datenverbunde (structs) und Klassen. Der Operator + kann bespielsweise nicht für zwei int-Operanden überladen werden, weil genau ein solcher Operator bereits existiert (Signatur: int, int). Um Beispiele zum Überladen von Operatoren vorlegen zu können, wird also ein selbst definierter Typ benötigt. Zu diesem Zweck soll der folgende Typ Bruch zur Verfügung stehen:

struct Bruch
{
 int Z; // Zähler
 int N; // Nenner
};

Operator *

Hier wird das Überladen des Multiplikationsoperators demonstriert. Sie sollten wissen, wie zwei Brüche miteinander multipliziert werden.
a / b * c / d = (a * c) / (b * d)

Die Kopfzeile

Die Kopfzeile eines Operators wird genau so gestaltet wie die einer Funktion, allerdings dürfen Sie den Namen nicht frei wählen. In diesem ersten Beispiel lautet der Name operator *.

Der hier zu erstellende Operator soll zwei Bruch-Operanden miteinander multiplizieren. Das Resultat dieser Multiplikation ist im Allgemeinen ein Bruch.
Die Operanden (Parameter) sind beide vom Typ Bruch.
Das Resultat ist vom Typ Bruch.

Dies führt zur folgenden Kopfzeile:
Bruch operator *(Bruch a, Bruch b)

Im Funktionsrumpf muss die Multiplikation implementiert und das Resultat zur Verfügung gestellt werden:
{
 Bruch res; 
// Der Ergebnisbruch
 res.Z = a.Z * b.Z; 
// Zähler miteinander multiplizieren
 res.N = a.N * b.N; 
// Nenner miteinander multiplizieren
 return res; 
// Ergebnisbruch liefern
}

Nun können zwei Bruch-Variable per * miteinander multipliziert werden:
Bruch b1 = {3,4}, b2 = {5,6}, b;
b = b1 * b2;
// b = 15/24 ungekürzt

Die obige Implementation der Bruchmultiplikation ist noch nicht optimal, weil der Ergebnisbruch in ungekürzter Form geliefert wird. Das Kürzen erfordert jedoch einige Vorarbeiten, die hier nicht wesentlich sind. Bei Bedarf kann dies in einem Sondergespräch genauer betrachtet werden (ggT per Euklidischer Algorithmus ...).

Die beiden Operanden (Parameter) müssen jedoch nicht vom gleichen Typ sein. Das Resultat kann auch einen anderen Typ besitzen. Betrachten sie einmal die folgende Multiplkation:
1 / 2 * 3 = 3 / 2
Der rechte Operand 3 ist kein Bruch sondern eine ganze Zahl. Diese Multiplikation kann mit der obigen Oparator-Implementation nicht durchgeführt werden. Dies erfordert vielmehr ein weiteres Überladen.
Der linke Operand ist vom Typ Bruch.
Der rechte Operand ist vom Typ int.
Das Resultat besitzt den Typ Bruch.

Daraus ergeben sich folgende mögliche Implementationen:

Bruch operator *(Bruch a, int b)
{
 Bruch res;
 res.Z = a.Z * b;
 res.N = a.N;
 return res;
}
oder Bruch operator *(Bruch a, int b)
{
 Bruch temp;
 temp.Z =  b;
 temp.N = 1;
 return a * temp;
}

Damit ist Folgendes möglich:
Bruch x = {3,4}, y;
y = x * 2;

Noch ist der Operator nicht kommuntativ.
y = 2 * x; ist nicht möglich.

Dafür ist eine Implementation notwendig, die einen linken Operanden bzw. einen ersten Parameter vom Typ int und einen rechten Operanden bzw. zweiten Parameter vom Typ Bruch verwendet:
Bruch operator *(int a, Bruch b)
{return b * a;}