Revision [c537ef6]
Letzte Änderung am 2020-05-25 17:57:21 durch Oksana Neopagitova
ADDITIONS
![image](/uploads/ObjProg04Operator/BMBF_Logo_klein.jpg?width=200)

## Objektorientierte Programmierung - Kapitel 4 - Operator - Überladung

_<span class="right">Inhalte von Dr. E. Nadobnyh</p>_


## 4.1. Grundlagen und Regeln


#### Operator-Überladung

Ein Operator ist überladen, wenn er je nach Typ der Operanden eine unterschiedliche Bedeutung hat.

Die meisten Operatoren für eingebauten Datentypen sind schon überladen.

**Beispiel**:

double a, b; short x, y;

a*b; x*y; _verschiedene Algorithmen



#### Operatorfunktion

In C++ gibt es die Möglichkeit , Operatoren für die Klassen zu definieren.

Eine Operatorfunktion ist eine Funktion mit einem besonderen Namen. Der Name der Operatorfunktion beginnt mit dem Schlüsselwort <span style="color:blue;">operator</span>, dem das Operatorsymbol folgt. Ausdrücke mit Operatoren sind intuitiver und daher schneller zu erfassen als Ausdrücke mit Funktionsaufrufe.



#### Zwei Definitionsmöglichkeiten

Eine Operatorfunktion kann entweder als globale Funktion oder als Methode einer Klasse definiert werden.

**1) Globale Operatorfunktion**

>> class Bruch{ };
>> Bruch operator+ (Bruch, Bruch );
>>
**2) Operatormethode**

>>bzw. Operatorfunktion als Methode

>> class Bruch
>> { public:
>>>>Bruch operator+ (Bruch x);
>> };



#### 4. Operator-Überladung

Aufruf der Operatorfunktion

Der Operator-Aufruf wird in einen Funktionsaufruf umgewandelt:

1) entweder in den Aufruf der globalen Operatorfunktion,
2) oder in den Aufruf der Operatormethode.

![image](/uploads/ObjProg04Operator/oop15.gif?width=450)



#### Mehrdeutigkeit

Wenn Compiler mehr als eine Aufrufmöglichkeit findet, wird der Aufruf bemängelt.

&rArr; Demo 1.



#### Globale Operatorfunktion

%%(cpp)
class Bruch;_ Vorwärtsdeklaration
Bruch operator+(Bruch a, Bruch b); _Deklaration

class Bruch
{_ Freundschaftserklärung
>> friend Bruch operator+(Bruch a, Bruch b);
};

main()
{ Bruch a, b, c;
>> c = a + b; _Aufruf
>> c=operator+(a,b);_ identisch
}
%%

&rArr; Demo 1.2



#### Operatormethode

%%(cpp)
class Bruch
{ public: Bruch operator+(Bruch b);
};
main()
{ Bruch a, b, c;
>> c = a + b; _Aufruf
>> c=a.operator+(b);_ identisch
}
%%



#### Operanden

Der zweistellige Operator hat zwei Operanden. Der erste Operand ist ein Objekt, für das die Methode aufgerufen wird.

&rArr; Demo 3.



#### Einsatzregeln

1) Es können bis auf wenige Ausnahmen alle Operatoren überladen werden.

2) Der Funktionsname besteht aus dem Schlüsselwort operator und dem Operatorzeichen.

3) Es können die übliche Operatoren überladen werden (z.B. *, +=, usw.).
Eine Definition von neuen Operatoren ist nicht möglich, z.B. neuen Operator ** zum Potenzieren. Andere Zeichen wie $ usw. sind nicht erlaubt.

&rArr; Demo 4. C++ Operatoren

4) Wenigstens ein Argument der Operatorfunktion muss ein class &#8211;Objekt sein, oder die Operatorfunktion muss eine Methode sein. Die Bedeutung der Operatoren für Standard-Typen lässt sich nicht umdefinieren.

5) Die Anzahl der Operanden eines Operators (Stelligkeit) kann nicht geändert werden, d.h. ein unärer Operator bleibt unär.

6) Einige Operatoren (z.B.: +, -, * ) können getrennt unär und binär überladen werden.

&rArr; Demo 5.

7) Der Operator-Aufruf wird in einen Funktionsaufruf umformuliert.

8) Die vorgegebenen Vorrangregeln können nicht verändert werden.

9) Die Reihenfolge der Auswertung (von links oder von rechts) bei der Operatoren mit gleicher Priorität bleibt erhalten.

10) Überladene Operatoren können keine Default-Parameter haben. (Eine Ausnahme ist der Funktionsoperator.)

&rArr; Demo 6 + Demo 7.

Einzelne Operatoren sind nicht überladbar:

<table class="data" width="80%" style="border:0">
<tr>
<td>
Operator
</td>
<td>
Bedeutung

</td>
</tr>
<tr>
<td>
sizeof

. <br/>

.* <br/>

:: <br/>

?:

</td>
<td>
Größe von Objekten

Zugriffsoperator (Strukturen, Unions, Klassen) <br/>
Zugriffsoperator für Elementzeiger <br/>

Bereichsoperator<br/>

Auswahloperator
</td>
</tr>
</table>


Operatoren, die nur als Methoden überladen werden können

<table class="data" width="80%" style="border:0">
<tr>
<td>
Operator
</td>
<td>
Bedeutung

</td>
</tr>
<tr>
<td>
= <br/>

[ ] <br/>

( ) <br/>

-> <br/>

(Typ)


</td>
<td>

Zuweisung <br/>

Indizierung <br/>

Funktionsaufruf bzw. Funktionsoperator <br/>

Elementzugriff für Zeiger <br/>

Typumwandlungsoperator
</td>
</tr>
</table>




## 4.2. Symmetrie der Operatoren


#### Symmetrische Operatoren

Einige binäre Operationen z.B. Addition sind kommutativ und ihre beide Operanden sind &#8222;gleichberechtigt&#8220;.

**Beispiel**:
Bruch a, b, c;
c=a+b;
c=b+a;



#### Gemischte Datentypen

Die Verwendung der Operanden vom Datentyp int soll auch möglich sein.

**Beispiel**:
Bruch a, b, c;
c=a+5;
c=5+a;



#### Symmetrie der globalen Operatorfunktionen

a) Ohne Konvertierungskonstruktor
Um gemischte Datentypen zu erlauben, kann man noch zwei globalen Operatorfunktionen entwerfen:

>> Bruch operator+(Bruch a, Bruch b);
>> Bruch operator+(Bruch a, long b);
>> Bruch operator+(long a, Bruch b);

b) Mit Konvertierungskonstruktor
Der Compiler konvertiert implizit den aktuellen
Parameter vom Typ long in Typ Bruch.

>> Bruch operator+(Bruch a, Bruch b);
>> Bruch (long x);

&rArr; Demo 8.



#### Asymmetrie der Operatormethode

Die Symmetrie geht verloren, wenn die Operatorfunktion als Methode implementiert wird.

**Beispiel**: Addition einer rationalen und einer ganzen Zahl

<table class="data" width="80%" style="border:0">
<tr>
<td>
Aufruf
</td>
<td>
Operatormethode

</td>
</tr>
<tr>
<td>
c = a + 3; <br/>
c = a.operator+(3);

</td>
<td>
Bruch Bruch::operator+(int x);
</td>
</tr>
<tr>
<td>
c = 3 + b; <br/>
c = 3 .operator+(b);

</td>
<td>
unmöglich
</td>
</tr>

</table>


Wenn die Symmetrie erhalten bleiben soll, dann ist den Operator als globale Funktion zu implementieren.



## 4.3. Einzelne Operatoren


#### Shift-Operatoren

In der iostream -Bibliothek wird der Links-Shift-Operator << als ein Ausgabeoperator und der Rechts-Shift-Operator >>
als ein Eingabeoperator interpretiert.

Um die iostream- Bibliothek für die Ein- und Ausgabe von Objekten des benutzerdefinierten Datentyps zu verwenden, sollen diese Operatoren überladen werden.


#### Globale Operatorfunktion oder Operatormethode

<table class="data" width="80%" style="border:0">
<tr>
<td>
Aufruf
</td>
<td>
Ersetzung durch

</td>
<td>
Zusammenfassung

</td>
</tr>
<tr>
<td rowspan="2">

Bruch c; <br/>
coutc;
</td>
<td>
cout.operator(c);

</td>
<td>
Diese Methode ist nicht
implementiert

</td>
</tr>

<tr>
<td>
operator(cout, c);
</td>
<td>
Die globale Fkt. ist die
einzige Möglichkeit
</td>
</tr>

</table>



**Rückgabe per Referenz für die Verkettung**

<table class="data" style="border:0">
<tr>
<td>
#include <iostream.h> <br/>

Bruch a; <br/> cout&#8220;a= &#8220;aendl;

</td>
</tr>
<tr>
<td>
ostream & operator (ostream & os, const Bruch & a) <br/>
{ ... <br/>
return os; <br/>
}
</td>
</tr>
</table>


&rArr; Demo 9



#### Implementierung globaler Operatorfunktion

Ohne der Freundschaftserklärung müssen die zusätzliche öffentliche Zugriffsmethoden vorhanden sein und in der globalen Funktion aufgerufen werden.

%%(cpp)
class Bruch
{ private: long za, ne; _za-Zaehler, ne-Nenner
>>public: long getZa(){return za;}
>>>>> long getNe(){return ne;}
};
ostream & operator(ostream & out, const Bruch & b);

ostream & operator(ostream & out, const Bruch & b)
{ outb.getZa()"/"b.getNe();
>>return out;
}
%%



#### Globale Operatorfunktion als friend-Funktion

Damit eine globale Operatorfunktion direkt auf private Attribute zugreifen kann, wird sie als friend-Funktion deklariert.

%%(cpp)
class Bruch
{ private: long za, ne;_ za-Zaehler, ne-Nenner
>>friend
>>ostream & operator(ostream & out, const Bruch & b);
};

ostream & operator(ostream & out, const Bruch & b)
{ outb.za<<"/"b.ne;
>> return out;
}

%%

&rArr; Demo 10.



#### Index-Operator

Für eingebauten Datentypen dient der Index-Operator normalerweise dem Zugriff auf Feldelemente, z.B.:
>>
short a, b[2];
b[1]=5;
a=b[1];

Im Ausdruck b[i] ist b der linke Operand und i der rechte Operand. Der rechte Operand heißt Index.

Für den nicht überladenen Index-Operator gelten folgende Einschränkungen:

>>1) Der linke Operand muß ein Zeiger oder ein Feldname sein.
>>2) Der rechte Operand muß ein ganzzahliger Ausdruck sein.
>>3) Der Ausdruck b[i] impliziert eine versteckte Zeigerarithmetik: *(b + i)



#### Index-Operator für eine Klasse

Für eine Klasse muss ein Index-Operator als Methode überladen werden.
>>
>> %%(cpp)
class Array
>> { public: float & operator[](int i);
>> }; %%

Für den überladenen Index-Operator gelten folgende Einschränkungen:

>>1) Der linke Operand muß ein Objekt der Klasse sein.
>>2) Der rechte Operand darf einen beliebigen Datentyp haben.
>>3) Der Ergebnis-Typ ist nicht festgelegt.
>>4) Das Ergebnis soll eine Referenz auf ein Objekt sein.

&rArr; Demo 11.



#### Zuweisungsoperator

Ein existierender Objekt wird durch eine Kopie eines anderen ersetzt.

Für jede Klasse ist ein Standard-Zuweisungsoperator implizit vordefiniert. Die Standardzuweisung erfolgt elementweise: d.h. für jedes Attribut des Objektes wird der entsprechende Zuweisungsoperator aufgerufen.

Der Zuweisungsoperator für Grunddatentypen bewirkt eine bitweise Kopie.


Wenn eine Klasse dynamische Attribute enthält, muß für diese Klasse ein expliziter (statt impliziter) Zuweisungsoperator überladen werden. Ein Zuweisungsoperator kann nur als eine Operatormethode überladen werden:

%%(cpp)
class Array
>>{ public: Array & operator=(const Array & neu);
>>}; %%

Es gibt zwei Formulierungen für den Aufruf:

%%(cpp)
>> Array a, b;
>> a = b; _impliziter Aufruf
>> a.operator=(b);_ expliziter Aufruf
%%

Ein Zuweisungsoperator soll immer das Objekt, für das der Operator aufgerufen wurde, als Referenz zurückliefern. Dies ermöglicht verkettete Zuweisungen.


>> Array a, b, c; a = b = c;

Im Zuweisungsoperator sollte getestet werden, ob ein Objekt sich selbst zugewiesen wird. Dies ermöglicht so genannter &#8222;Zuweisung an sich selbst&#8220;.

%%(cpp)
Array a; a = a;

>> Array & Array::operator=(const Array & neu)
>> { if(this
##### & neu) return *this;
>>>> . . .
>>>> return *this;
>> } %%
>>
Der Zuweisungsoperator ist im Prinzip eine Kombination aus Destruktor und Kopierkonstruktor.

%%(cpp)
typedef ... T;
class Array
{ private: T* z; int n;
>> public:
>>> Array & operator=(const Array & neu)
>>> { if(this & neu) return *this;
>>>> delete[] z; _alten Speicher freigeben
>>>> n=neu.n; z=new T[n];_ neuen reservieren
>>>> for(int i=0; i<n; i++) z[i]=neu.z[i]; _Kopie
>>>> return *this;
>>> }
};
%%

&rArr; Demo 12.

Auch der Funktionsaufruf ist ein Operator, der für eigene Klassen definiert werden kann.

**Synonyme**: Funktionsoperator, Klammeroperator, operator(), Funktionsaufrufoperator.

Im folgenden Prinzipbeispiel wird ein parameterlose unktionsoperator deklariert:

class XXX
{ &#8230;
>>public: void operator() ();
};

Ein Objekt mit der Funktionsoperator wird Funktionsobjekt der Funktor benannt. Die Funktionsobjekte werden in der C++-Standardbibliothek verwendet.


Der Funktionsoperator bringt überraschende Konsequenzen: ein Funktionsobjekt kann wie eine Funktion aufgerufen werden:

Es sieht so aus, als würde eine globale Funktion x1() aufgerufen. Tatsächlich wird der Funktionsoperator des Objektes x1 aufgerufen.

![image](/uploads/ObjProg04Operator/oop16.gif?width=200)

Der explizite Aufruf des Funktionsoperators ist syntaktisch ebenfalls erlaubt:

![image](/uploads/ObjProg04Operator/oop17.gif?width=200)

Die Funktionsobjekte können wie andere Methoden mehrfach überladen werden, z.B.:

%%(cpp)
class Polynom
{ float a, b, c;
public:
>> Polynom(float aa, float bb, float cc){a=aa; b=bb; c=cc;}
>> float operator( )(float x){ return a*x*x + b*x + c; }
>> float operator( )(float a, float b, float c, float x)
>> { return a*x*x + b*x + c;_ Funktionswert
>> }
};
int main()
{ Polynom po(5, 6, 7);
>> cout po(3)&#8220; &#8220;po(3, -2, -7, 5); _70 58
} %%


Ein wichtiger Vorteil ist, dass ein Funktionsobjekt statt Funktionszeiger als Parameter zu einer Funktion übergeben werden könnte. Das ist die objektorientierte Alternative.

**Beispiel**:

%%(cpp)
double Doppelt (Polynom p, float x)
>> { return 2*p(x);
>> }
>> int main()
>> { Polynom po(5, 6, 7);
>>>> cout Doppelt(po, 3)" &#8220;
>>>>>> Doppelt(Polynom(3, -2, -7), 5);_ 140 116

>> } %%

&rArr; Demo 13, 14.



## 4.4. Iterator-Operatoren


#### Behälter und Iterator

Ein <span style="text-decoration:underline;">Behälter </span>(container oder collection) ist ein Objekt, das zum Verwalten von anderen Objekten (Elementen) dient.

Jedes Element in einem Behälter besitzt eine bestimmte <span style="text-decoration:underline;">Position</span>, in der es abgelegt ist. Man kann über die Position direkt auf das einzelne Element zugreifen. Die Darstellung der Position ist von der Implementierung des Behälters abhängig. Zeiger und Indexe sind bekannte Bespiele dafür.

Ein <span style="text-decoration:underline;">Iterator </span>ist ein Objekt, das eine Position in einem Behälter repräsentiert (verweist, zeigt). Ein Iterator dient dazu, von den Implementierungsdetails des Behälters zu abstrahieren. Begriffsverwirrung: Mit dem Begriff &#8222;Iterator&#8220; können auch eine Klasse und ein Konzept bezeichnet werden.

**Prinzipbeispiel**:

![image](/uploads/ObjProg04Operator/oop18.gif?width=500)



#### Iterator-Operatoren

1. **Operatoren**zum Iterieren (Durchwandern). Die Position, welche durch einen Iterator repräsentiert wird, wird zur Position des nächsten (oder vorigen) Elementes im Behälter gewechselt. Beispielsweise wechselt ein Inkrement-Operator++ auf Position des nächsten Elementes.


2. **Vergleichsoperatoren**. Zwei Iteratoren können verglichen werden, z.B. der Gleich-Operator
##### liefert true, wenn zwei Iteratoren auf dasselbe Element verweisen.


!= < > <= >=

3. **Zugriffsoperatoren**. Das Element, welches durch einen Iterator repräsentiert wird, wird gelesen oder geändert (überschrieben). Beispiel: ein Inhalts-Operator* des Iterators liefert die Referenz auf das repräsentierten Element.

* -> [ ]



#### Iterator als geschachtelte Klasse

**Prinzipbeispiel**

typedef &#8230; T; _Typ des Elementes

![image](/uploads/ObjProg04Operator/oop19.gif?width=500)



#### Anwendung von Iteratoren

1) Die Verbindung zwischen Behälter und Iterator wird mit den Methoden &#8222;start&#8220; und &#8222;ende&#8220; hergestellt.

Behaelter b;
Behaelter::iterator s= b.start();
Behaelter::iterator e= b.ende();

2) Ein Inkrement-Operator schiebt den Iterator auf die nächste Position: s++;

![image](/uploads/ObjProg04Operator/oop20.gif?width=550)



#### Vorteile von Iteratoren

1) Der Benutzer muss nicht kennen, welche Datenstruktur der Behälter besitzt.
2) Wenn eine Iterator-Klasse als eine geschachtelte Klasse definiert ist, dann ist sie ein Bestandteil der Behälterdefinition. Dann muss ein Benutzer viele Besonderheitendes Iterators nicht kennen und kann den Iterator über üblichen Namen ansprechen.

**Prinzipbeispiel:**

%%(cpp)
main()
{
Behaelter b;_ Behaelter-Definition
Behaelter::iterator i; _Iterator-Definition

for (i=b.start( ); i!=b.ende( ); ++i)
>>>>> cout<<*i<<" ";
>> }
%%

&rArr; Demo 13



#### Inhalts-Operator

Der Inhaltsoperator * (Dereferenzierungsoperator, Verweisoperator, Indirektionsoperator) liefert eine Referenz auf das Element, an dessen Position sich der Iterator befindet.

**Prinzipbeispiel:**

%%(cpp)
typedef ... T;_ Typ des Elementes
>> class Behaelter {
>>>>...
>>> public:
>>> class iterator {
>>> T* c; _Zeiger auf aktuelles Element
>> public:
>>>>T & operator* (void) {return *c;}
>> };
%%


Die Verwendung des Inhaltsoperators *i bedeutet einen lesenden oder schreibenden Zugriff auf das Element, deren Position der Iterator i enthält.

**Beispiel:**

%%(cpp)
typedef &#8230; T;_ Typ des Elementes
>> main()
>> { Behaelter b;
>>> Behaelter::iterator i= b.start( ); _Initialisierung
>>> T tmp= *i;_ lesender Zugriff auf das Element
>>> *i = tmp; _schreibender Zugriff auf das Element
>> }
%%

**Anmerkung:**
Der Operator * kann getrennt unär (Inhaltsoperator) und binär (Multiplikationsoperator) überladen werden.



#### Inkrement-Operator

Die Position, welche ein Iterator repräsentiert, wird zur Position des nächsten Elementes im Behälter gewechselt. Dabei ändert sich ein Iterator selbst.

Außerdem liefert dieser Operator einen Iterator als Ergebnis zurück. Präfix-Operator liefert den veränderten Iterator. Postfix-Operator liefert den ursprünglichen Iterator.

**Beispiel für Präfix-Operator**

%%(cpp)
class Behaelter
{ struct KN{ ...; KN* next;};
public:
>> class iterator
>> { KN* c;_ Zeiger auf aktuellen Knoten
>>>public:
>>> iterator & operator++() { c = c->next; return *this;}
>> };
}; %%
DELETIONS
![image](/uploads/ObjProg04Operator/BMBF_Logo_klein.jpg?width=200)
# Objektorientierte Programmierung - Kapitel 4 - Operator - Überladung
_<span class="right">Inhalte von Dr. E. Nadobnyh</p>_
## 4.1. Grundlagen und Regeln
#### Operator-Überladung

Ein Operator ist überladen, wenn er je nach Typ der Operanden eine unterschiedliche Bedeutung hat.

Die meisten Operatoren für eingebauten Datentypen sind schon überladen.

**Beispiel**:

double a, b; short x, y;

a*b; x*y; _verschiedene Algorithmen

#### Operatorfunktion

In C++ gibt es die Möglichkeit , Operatoren für die Klassen zu definieren.

Eine Operatorfunktion ist eine Funktion mit einem besonderen Namen. Der Name der Operatorfunktion beginnt mit dem Schlüsselwort <span style="color:blue;">operator</span>, dem das Operatorsymbol folgt. Ausdrücke mit Operatoren sind intuitiver und daher schneller zu erfassen als Ausdrücke mit Funktionsaufrufe.
#### Zwei Definitionsmöglichkeiten

Eine Operatorfunktion kann entweder als globale Funktion oder als Methode einer Klasse definiert werden.

**1) Globale Operatorfunktion**

>> class Bruch{ };
>> Bruch operator+ (Bruch, Bruch );
>>
**2) Operatormethode**
>>bzw. Operatorfunktion als Methode

>> class Bruch
>> { public:
>>>>Bruch operator+ (Bruch x);
>> };
#### 4. Operator-Überladung
Aufruf der Operatorfunktion

Der Operator-Aufruf wird in einen Funktionsaufruf umgewandelt:
1) entweder in den Aufruf der globalen Operatorfunktion,
2) oder in den Aufruf der Operatormethode.

![image](/uploads/ObjProg04Operator/oop15.gif?width=450)
#### Mehrdeutigkeit

Wenn Compiler mehr als eine Aufrufmöglichkeit findet, wird der Aufruf bemängelt.

&rArr; Demo 1.
#### Globale Operatorfunktion

%%(cpp)
class Bruch;_ Vorwärtsdeklaration
Bruch operator+(Bruch a, Bruch b); _Deklaration

class Bruch
{_ Freundschaftserklärung
>> friend Bruch operator+(Bruch a, Bruch b);
};

main()
{ Bruch a, b, c;
>> c = a + b; _Aufruf
>> c=operator+(a,b);_ identisch
}
%%

&rArr; Demo 1.2
#### Operatormethode

%%(cpp)
class Bruch
{ public: Bruch operator+(Bruch b);
};
main()
{ Bruch a, b, c;
>> c = a + b; _Aufruf
>> c=a.operator+(b);_ identisch
}
%%
#### Operanden

Der zweistellige Operator hat zwei Operanden. Der erste Operand ist ein Objekt, für das die Methode aufgerufen wird.

&rArr; Demo 3.
#### Einsatzregeln

1) Es können bis auf wenige Ausnahmen alle Operatoren überladen werden.

2)Der Funktionsname besteht aus dem Schlüsselwort operator und dem Operatorzeichen.

3) Es können die übliche Operatoren überladen werden (z.B. *, +=, usw.).
Eine Definition von neuen Operatoren ist nicht möglich, z.B. neuen Operator ** zum Potenzieren. Andere Zeichen wie $ usw. sind nicht erlaubt.

&rArr; Demo 4. C++ Operatoren
4) Wenigstens ein Argument der Operatorfunktion muss ein class &#8211;Objekt sein, oder die Operatorfunktion muss eine Methode sein. Die Bedeutung der Operatoren für Standard-Typen lässt sich nicht umdefinieren.

5) Die Anzahl der Operanden eines Operators (Stelligkeit) kann nicht geändert werden, d.h. ein unärer Operator bleibt unär.

6) Einige Operatoren (z.B.: +, -, * ) können getrennt unär und binär überladen werden.

&rArr; Demo 5.
7) Der Operator-Aufruf wird in einen Funktionsaufruf umformuliert.

8) Die vorgegebenen Vorrangregeln können nicht verändert werden.

9) Die Reihenfolge der Auswertung (von links oder von rechts) bei der Operatoren mit gleicher Priorität bleibt erhalten.

10) Überladene Operatoren können keine Default-Parameter haben. (Eine Ausnahme ist der Funktionsoperator.)

&rArr; Demo 6 + Demo 7.
Einzelne Operatoren sind nicht überladbar:
<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Operator
>>></td>
>>><td>
>>>>Bedeutung

>>></td>
>></tr>
>><tr>
>>><td>
>>>>sizeof

. <br/>

.* <br/>

:: <br/>

?:
>>></td>
>>><td>
>>>>Größe von Objekten

Zugriffsoperator (Strukturen, Unions, Klassen) <br/>
Zugriffsoperator für Elementzeiger <br/>

Bereichsoperator<br/>

Auswahloperator
>>></td>
>></tr>
</table>
Operatoren, die nur als Methoden überladen werden können

<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Operator
>>></td>
>>><td>
>>>>Bedeutung

>>></td>
>></tr>
>><tr>
>>><td>
= <br/>

[ ] <br/>

( ) <br/>

-> <br/>

(Typ)

>>></td>
>>><td>

Zuweisung <br/>

Indizierung <br/>

Funktionsaufruf bzw. Funktionsoperator <br/>

Elementzugriff für Zeiger <br/>

Typumwandlungsoperator
>>></td>
>></tr>
</table>
## 4.2. Symmetrie der Operatoren
#### Symmetrische Operatoren

Einige binäre Operationen z.B. Addition sind kommutativ und ihre beide Operanden sind &#8222;gleichberechtigt&#8220;.

**Beispiel**:
Bruch a, b, c;
c=a+b;
c=b+a;


#### Gemischte Datentypen

Die Verwendung der Operanden vom Datentyp int soll auch möglich sein.

**Beispiel**:
Bruch a, b, c;
c=a+5;
c=5+a;

#### Symmetrie der globalen Operatorfunktionen

a) Ohne Konvertierungskonstruktor
Um gemischte Datentypen zu erlauben, kann man noch zwei globalen Operatorfunktionen entwerfen:

>> Bruch operator+(Bruch a, Bruch b);
>> Bruch operator+(Bruch a, long b);
>> Bruch operator+(long a, Bruch b);

b) Mit Konvertierungskonstruktor
Der Compiler konvertiert implizit den aktuellen
Parameter vom Typ long in Typ Bruch.

>> Bruch operator+(Bruch a, Bruch b);
>> Bruch (long x);

&rArr; Demo 8.
#### Asymmetrie der Operatormethode

Die Symmetrie geht verloren, wenn die Operatorfunktion als Methode implementiert wird.

**Beispiel**: Addition einer rationalen und einer ganzen Zahl
<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Aufruf
>>></td>
>>><td>
>>>>Operatormethode
>>></td>
>></tr>
>><tr>
>>><td>
>>> c = a + 3; <br/>
c = a.operator+(3);

>>></td>
>>><td>
>>>>Bruch Bruch::operator+(int x);
>>></td>
>></tr>
>><tr>
>>><td>
>>> c = 3 + b; <br/>
c = 3 .operator+(b);

>>></td>
>>><td>
>>>>unmöglich
>>></td>
>></tr>
</table>
Wenn die Symmetrie erhalten bleiben soll, dann ist den Operator als globale Funktion zu implementieren.

## 4.3. Einzelne Operatoren
#### Shift-Operatoren

In der iostream -Bibliothek wird der Links-Shift-Operator << als ein Ausgabeoperator und der Rechts-Shift-Operator >>
als ein Eingabeoperator interpretiert.
Um die iostream- Bibliothek für die Ein- und Ausgabe von Objekten des benutzerdefinierten Datentyps zu verwenden, sollen diese Operatoren überladen werden.

#### Globale Operatorfunktion oder Operatormethode

<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Aufruf
>>></td>
>>><td>
>>>>Ersetzung durch
>>></td>
>>><td>
>>>>Zusammenfassung
>>></td>
>></tr>
>><tr>
>>><td rowspan="2">
>>>>
Bruch c; <br/>
coutc;
>>></td>
>>><td>
>>>>cout.operator(c);
>>></td>
>>><td>
>>>>Diese Methode ist nicht
implementiert
>>></td>
>></tr>

>><tr>
>>><td>
>>>>operator(cout, c);
>>></td>
>>><td>
>>>>Die globale Fkt. ist die
einzige Möglichkeit
>>></td>
>></tr>
</table>
**Rückgabe per Referenz für die Verkettung**
<table class="data" style="border:0">
>><tr>
>>><td>
>>>>#include <iostream.h> <br/>

Bruch a; <br/> cout&#8220;a= &#8220;aendl;
>>
>>></td>
>></tr>
>><tr>
>>><td>
>>>>ostream & operator (ostream & os, const Bruch & a) <br/>
{ ... <br/>
>> return os; <br/>
}
>>></td>
>></tr>
</table>
&rArr; Demo 9
#### Implementierung globaler Operatorfunktion

Ohne der Freundschaftserklärung müssen die zusätzliche öffentliche Zugriffsmethoden vorhanden sein und in der globalen Funktion aufgerufen werden.
%%(cpp)
class Bruch
{ private: long za, ne; _za-Zaehler, ne-Nenner
>>public: long getZa(){return za;}
>>>>> long getNe(){return ne;}
};
ostream & operator(ostream & out, const Bruch & b);

ostream & operator(ostream & out, const Bruch & b)
{ outb.getZa()"/"b.getNe();
>>return out;
}
%%
#### Globale Operatorfunktion als friend-Funktion
Damit eine globale Operatorfunktion direkt auf private Attribute zugreifen kann, wird sie als friend-Funktion deklariert.
%%(cpp)
class Bruch
{ private: long za, ne;_ za-Zaehler, ne-Nenner
>>friend
>>ostream & operator(ostream & out, const Bruch & b);
};

ostream & operator(ostream & out, const Bruch & b)
{ outb.za<<"/"b.ne;
>> return out;
}

%%
&rArr; Demo 10.
#### Index-Operator

Für eingebauten Datentypen dient der Index-Operator normalerweise dem Zugriff auf Feldelemente, z.B.:
>>
short a, b[2];
b[1]=5;
a=b[1];

Im Ausdruck b[i] ist b der linke Operand und i der rechte Operand. Der rechte Operand heißt Index.

Für den nicht überladenen Index-Operator gelten folgende Einschränkungen:
>>1) Der linke Operand muß ein Zeiger oder ein Feldname sein.
>>2) Der rechte Operand muß ein ganzzahliger Ausdruck sein.
>>3) Der Ausdruck b[i] impliziert eine versteckte Zeigerarithmetik: *(b + i)
#### Index-Operator für eine Klasse

Für eine Klasse muss ein Index-Operator als Methode überladen werden.
>>
>> %%(cpp)
class Array
>> { public: float & operator[](int i);
>> }; %%

Für den überladenen Index-Operator gelten folgende Einschränkungen:
>>1) Der linke Operand muß ein Objekt der Klasse sein.
>>2) Der rechte Operand darf einen beliebigen Datentyp haben.
>>3) Der Ergebnis-Typ ist nicht festgelegt.
>>4) Das Ergebnis soll eine Referenz auf ein Objekt sein.

&rArr; Demo 11.
#### Zuweisungsoperator

Ein existierender Objekt wird durch eine Kopie eines anderen ersetzt.

Für jede Klasse ist ein Standard-Zuweisungsoperator implizit vordefiniert. Die Standardzuweisung erfolgt elementweise: d.h. für jedes Attribut des Objektes wird der entsprechende Zuweisungsoperator aufgerufen.

Der Zuweisungsoperator für Grunddatentypen bewirkt eine bitweise Kopie.


Wenn eine Klasse dynamische Attribute enthält, muß für diese Klasse ein expliziter (statt impliziter) Zuweisungsoperator überladen werden. Ein Zuweisungsoperator kann nur als eine Operatormethode überladen werden:

%%(cpp)
class Array
>>{ public: Array & operator=(const Array & neu);
>>}; %%

Es gibt zwei Formulierungen für den Aufruf:
%%(cpp)
>> Array a, b;
>> a = b; _impliziter Aufruf
>> a.operator=(b);_ expliziter Aufruf
%%
Ein Zuweisungsoperator soll immer das Objekt, für das der Operator aufgerufen wurde, als Referenz zurückliefern. Dies ermöglicht verkettete Zuweisungen.
>> Array a, b, c; a = b = c;

Im Zuweisungsoperator sollte getestet werden, ob ein Objekt sich selbst zugewiesen wird. Dies ermöglicht so genannter &#8222;Zuweisung an sich selbst&#8220;.
%%(cpp)
Array a; a = a;

>> Array & Array::operator=(const Array & neu)
>> { if(this
##### & neu) return *this;
>>>> . . .
>>>> return *this;
>> } %%
>>
Der Zuweisungsoperator ist im Prinzip eine Kombination aus Destruktor und Kopierkonstruktor.

%%(cpp)
typedef ... T;
class Array
{ private: T* z; int n;
>> public:
>>> Array & operator=(const Array & neu)
>>> { if(this & neu) return *this;
>>>> delete[] z; _alten Speicher freigeben
>>>> n=neu.n; z=new T[n];_ neuen reservieren
>>>> for(int i=0; i<n; i++) z[i]=neu.z[i]; _Kopie
>>>> return *this;
>>> }
};
%%

&rArr; Demo 12.
Auch der Funktionsaufruf ist ein Operator, der für eigene Klassen definiert werden kann.

**Synonyme**: Funktionsoperator, Klammeroperator, operator(), Funktionsaufrufoperator.

Im folgenden Prinzipbeispiel wird ein parameterlose unktionsoperator deklariert:

class XXX
{ &#8230;
>>public: void operator() ();
};

Ein Objekt mit der Funktionsoperator wird Funktionsobjekt der Funktor benannt. Die Funktionsobjekte werden in der C++-Standardbibliothek verwendet.

Der Funktionsoperator bringt überraschende Konsequenzen: ein Funktionsobjekt kann wie eine Funktion aufgerufen werden:
Es sieht so aus, als würde eine globale Funktion x1() aufgerufen. Tatsächlich wird der Funktionsoperator des Objektes x1 aufgerufen.
![image](/uploads/ObjProg04Operator/oop16.gif?width=200)
Der explizite Aufruf des Funktionsoperators ist syntaktisch ebenfalls erlaubt:
![image](/uploads/ObjProg04Operator/oop17.gif?width=200)
Die Funktionsobjekte können wie andere Methoden mehrfach überladen werden, z.B.:
%%(cpp)
class Polynom
{ float a, b, c;
public:
>> Polynom(float aa, float bb, float cc){a=aa; b=bb; c=cc;}
>> float operator( )(float x){ return a*x*x + b*x + c; }
>> float operator( )(float a, float b, float c, float x)
>> { return a*x*x + b*x + c;_ Funktionswert
>> }
};
int main()
{ Polynom po(5, 6, 7);
>> cout po(3)&#8220; &#8220;po(3, -2, -7, 5); _70 58
} %%
Ein wichtiger Vorteil ist, dass ein Funktionsobjekt statt Funktionszeiger als Parameter zu einer Funktion übergeben werden könnte. Das ist die objektorientierte Alternative.
**Beispiel**:

%%(cpp)
double Doppelt (Polynom p, float x)
>> { return 2*p(x);
>> }
>> int main()
>> { Polynom po(5, 6, 7);
>>>> cout Doppelt(po, 3)" &#8220;
>>>>>> Doppelt(Polynom(3, -2, -7), 5);_ 140 116

>> } %%

&rArr; Demo 13, 14.
## 4.4. Iterator-Operatoren
#### Behälter und Iterator

Ein <span style="text-decoration:underline;">Behälter </span>(container oder collection) ist ein Objekt, das zum Verwalten von anderen Objekten (Elementen) dient.

Jedes Element in einem Behälter besitzt eine bestimmte <span style="text-decoration:underline;">Position</span>, in der es abgelegt ist. Man kann über die Position direkt auf das einzelne Element zugreifen. Die Darstellung der Position ist von der Implementierung des Behälters abhängig. Zeiger und Indexe sind bekannte Bespiele dafür.

Ein <span style="text-decoration:underline;">Iterator </span>ist ein Objekt, das eine Position in einem Behälter repräsentiert (verweist, zeigt). Ein Iterator dient dazu, von den Implementierungsdetails des Behälters zu abstrahieren. Begriffsverwirrung: Mit dem Begriff &#8222;Iterator&#8220; können auch eine Klasse und ein Konzept bezeichnet werden.
**Prinzipbeispiel**:
![image](/uploads/ObjProg04Operator/oop18.gif?width=500)
#### Iterator-Operatoren

1. **Operatoren**zum Iterieren (Durchwandern). Die Position, welche durch einen Iterator repräsentiert wird, wird zur Position des nächsten (oder vorigen) Elementes im Behälter gewechselt. Beispielsweise wechselt ein Inkrement-Operator++ auf Position des nächsten Elementes.
++ -- + - += -=

2. **Vergleichsoperatoren**. Zwei Iteratoren können verglichen werden, z.B. der Gleich-Operator
##### liefert true, wenn zwei Iteratoren auf dasselbe Element verweisen.
!= < > <= >=

3. **Zugriffsoperatoren**. Das Element, welches durch einen Iterator repräsentiert wird, wird gelesen oder geändert (überschrieben). Beispiel: ein Inhalts-Operator* des Iterators liefert die Referenz auf das repräsentierten Element.
* -> [ ]
#### Iterator als geschachtelte Klasse
**Prinzipbeispiel**

typedef &#8230; T; _Typ des Elementes
![image](/uploads/ObjProg04Operator/oop19.gif?width=500)
#### Anwendung von Iteratoren

1) Die Verbindung zwischen Behälter und Iterator wird mit den Methoden &#8222;start&#8220; und &#8222;ende&#8220; hergestellt.
Behaelter b;
Behaelter::iterator s= b.start();
Behaelter::iterator e= b.ende();

2) Ein Inkrement-Operator schiebt den Iterator auf die nächste Position: s++;
![image](/uploads/ObjProg04Operator/oop20.gif?width=550)
#### Vorteile von Iteratoren

1) Der Benutzer muss nicht kennen, welche Datenstruktur der Behälter besitzt.
2) Wenn eine Iterator-Klasse als eine geschachtelte Klasse definiert ist, dann ist sie ein Bestandteil der Behälterdefinition. Dann muss ein Benutzer viele Besonderheitendes Iterators nicht kennen und kann den Iterator über üblichen Namen ansprechen.

**Prinzipbeispiel:**
%%(cpp)
main()
{
Behaelter b;_ Behaelter-Definition
Behaelter::iterator i; _Iterator-Definition
for (i=b.start( ); i!=b.ende( ); ++i)
>>>>> cout<<*i<<" ";
>> }
%%
&rArr; Demo 13
#### Inhalts-Operator

Der Inhaltsoperator * (Dereferenzierungsoperator, Verweisoperator, Indirektionsoperator) liefert eine Referenz auf das Element, an dessen Position sich der Iterator befindet.

**Prinzipbeispiel:**
%%(cpp)
typedef ... T;_ Typ des Elementes
>> class Behaelter {
>>>>...
>>> public:
>>> class iterator {
>>> T* c; _Zeiger auf aktuelles Element
>> public:
>>>>T & operator* (void) {return *c;}
>> };
%%

Die Verwendung des Inhaltsoperators *i bedeutet einen lesenden oder schreibenden Zugriff auf das Element, deren Position der Iterator i enthält.

**Beispiel:**
%%(cpp)
typedef &#8230; T;_ Typ des Elementes
>> main()
>> { Behaelter b;
>>> Behaelter::iterator i= b.start( ); _Initialisierung
>>> T tmp= *i;_ lesender Zugriff auf das Element
>>> *i = tmp; _schreibender Zugriff auf das Element
>> }
%%
**Anmerkung:**
Der Operator * kann getrennt unär (Inhaltsoperator) und binär (Multiplikationsoperator) überladen werden.
#### Inkrement-Operator

Die Position, welche ein Iterator repräsentiert, wird zur Position des nächsten Elementes im Behälter gewechselt. Dabei ändert sich ein Iterator selbst.

Außerdem liefert dieser Operator einen Iterator als Ergebnis zurück. Präfix-Operator liefert den veränderten Iterator. Postfix-Operator liefert den ursprünglichen Iterator.

**Beispiel für Präfix-Operator**
%%(cpp)
class Behaelter
{ struct KN{ ...; KN* next;};
public:
>> class iterator
>> { KN* c;_ Zeiger auf aktuellen Knoten
>>>public:
>>> iterator & operator++() { c = c->next; return *this;}
>> };
}; %%
***
CategoryObjektorientierteProgrammierung
Revision [fd29c22]
Bearbeitet am 2017-08-16 15:16:50 von ClaudiaMichel
ADDITIONS
CategoryObjektorientierteProgrammierung
DELETIONS
CategoryDelete
Revision [43cb810]
Bearbeitet am 2016-09-27 12:42:05 von NicoleHennemann
ADDITIONS
CategoryDelete
DELETIONS
CategoryObjProg
Revision [14fab0e]
Bearbeitet am 2013-04-29 18:53:07 von RonnyGertler
ADDITIONS
#### Iterator als geschachtelte Klasse
**Prinzipbeispiel**

typedef &#8230; T; _Typ des Elementes
![image](/uploads/ObjProg04Operator/oop19.gif?width=500)
#### Anwendung von Iteratoren

1) Die Verbindung zwischen Behälter und Iterator wird mit den Methoden &#8222;start&#8220; und &#8222;ende&#8220; hergestellt.
Behaelter b;
Behaelter::iterator s= b.start();
Behaelter::iterator e= b.ende();

2) Ein Inkrement-Operator schiebt den Iterator auf die nächste Position: s++;
![image](/uploads/ObjProg04Operator/oop20.gif?width=550)
#### Vorteile von Iteratoren

1) Der Benutzer muss nicht kennen, welche Datenstruktur der Behälter besitzt.
2) Wenn eine Iterator-Klasse als eine geschachtelte Klasse definiert ist, dann ist sie ein Bestandteil der Behälterdefinition. Dann muss ein Benutzer viele Besonderheitendes Iterators nicht kennen und kann den Iterator über üblichen Namen ansprechen.

**Prinzipbeispiel:**
%%(cpp)
main()
{
Behaelter b;_ Behaelter-Definition
Behaelter::iterator i; _Iterator-Definition
for (i=b.start( ); i!=b.ende( ); ++i)
>>>>> cout<<*i<<" ";
>> }
%%
&rArr; Demo 13
#### Inhalts-Operator

Der Inhaltsoperator * (Dereferenzierungsoperator, Verweisoperator, Indirektionsoperator) liefert eine Referenz auf das Element, an dessen Position sich der Iterator befindet.

**Prinzipbeispiel:**
%%(cpp)
typedef ... T;_ Typ des Elementes
>> class Behaelter {
>>>>...
>>> public:
>>> class iterator {
>>> T* c; _Zeiger auf aktuelles Element
>> public:
>>>>T & operator* (void) {return *c;}
>> };
%%

Die Verwendung des Inhaltsoperators *i bedeutet einen lesenden oder schreibenden Zugriff auf das Element, deren Position der Iterator i enthält.

**Beispiel:**
%%(cpp)
typedef &#8230; T;_ Typ des Elementes
>> main()
>> { Behaelter b;
>>> Behaelter::iterator i= b.start( ); _Initialisierung
>>> T tmp= *i;_ lesender Zugriff auf das Element
>>> *i = tmp; _schreibender Zugriff auf das Element
>> }
%%
**Anmerkung:**
Der Operator * kann getrennt unär (Inhaltsoperator) und binär (Multiplikationsoperator) überladen werden.
#### Inkrement-Operator

Die Position, welche ein Iterator repräsentiert, wird zur Position des nächsten Elementes im Behälter gewechselt. Dabei ändert sich ein Iterator selbst.

Außerdem liefert dieser Operator einen Iterator als Ergebnis zurück. Präfix-Operator liefert den veränderten Iterator. Postfix-Operator liefert den ursprünglichen Iterator.

**Beispiel für Präfix-Operator**
%%(cpp)
class Behaelter
{ struct KN{ ...; KN* next;};
public:
>> class iterator
>> { KN* c;_ Zeiger auf aktuellen Knoten
>>>public:
>>> iterator & operator++() { c = c->next; return *this;}
>> };
}; %%
Revision [65277b2]
Bearbeitet am 2013-03-29 00:58:52 von RonnyGertler
ADDITIONS
a*b; x*y; _verschiedene Algorithmen
#### 4. Operator-Überladung
Aufruf der Operatorfunktion

Der Operator-Aufruf wird in einen Funktionsaufruf umgewandelt:
1) entweder in den Aufruf der globalen Operatorfunktion,
2) oder in den Aufruf der Operatormethode.

![image](/uploads/ObjProg04Operator/oop15.gif?width=450)
#### Mehrdeutigkeit

Wenn Compiler mehr als eine Aufrufmöglichkeit findet, wird der Aufruf bemängelt.

&rArr; Demo 1.
#### Globale Operatorfunktion

%%(cpp)
class Bruch;_ Vorwärtsdeklaration
Bruch operator+(Bruch a, Bruch b); _Deklaration

class Bruch
{_ Freundschaftserklärung
>> friend Bruch operator+(Bruch a, Bruch b);
};

main()
{ Bruch a, b, c;
>> c = a + b; _Aufruf
>> c=operator+(a,b);_ identisch
}
%%

&rArr; Demo 1.2
#### Operatormethode

%%(cpp)
class Bruch
{ public: Bruch operator+(Bruch b);
};
main()
{ Bruch a, b, c;
>> c = a + b; _Aufruf
>> c=a.operator+(b);_ identisch
}
%%
#### Operanden

Der zweistellige Operator hat zwei Operanden. Der erste Operand ist ein Objekt, für das die Methode aufgerufen wird.

&rArr; Demo 3.
#### Einsatzregeln

1) Es können bis auf wenige Ausnahmen alle Operatoren überladen werden.

2)Der Funktionsname besteht aus dem Schlüsselwort operator und dem Operatorzeichen.

3) Es können die übliche Operatoren überladen werden (z.B. *, +=, usw.).
Eine Definition von neuen Operatoren ist nicht möglich, z.B. neuen Operator ** zum Potenzieren. Andere Zeichen wie $ usw. sind nicht erlaubt.

&rArr; Demo 4. C++ Operatoren
4) Wenigstens ein Argument der Operatorfunktion muss ein class &#8211;Objekt sein, oder die Operatorfunktion muss eine Methode sein. Die Bedeutung der Operatoren für Standard-Typen lässt sich nicht umdefinieren.

5) Die Anzahl der Operanden eines Operators (Stelligkeit) kann nicht geändert werden, d.h. ein unärer Operator bleibt unär.

6) Einige Operatoren (z.B.: +, -, * ) können getrennt unär und binär überladen werden.

&rArr; Demo 5.
7) Der Operator-Aufruf wird in einen Funktionsaufruf umformuliert.

8) Die vorgegebenen Vorrangregeln können nicht verändert werden.

9) Die Reihenfolge der Auswertung (von links oder von rechts) bei der Operatoren mit gleicher Priorität bleibt erhalten.

10) Überladene Operatoren können keine Default-Parameter haben. (Eine Ausnahme ist der Funktionsoperator.)

&rArr; Demo 6 + Demo 7.
Einzelne Operatoren sind nicht überladbar:
<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Operator
>>></td>
>>><td>
>>>>Bedeutung

>>></td>
>></tr>
>><tr>
>>><td>
>>>>sizeof

. <br/>

.* <br/>

:: <br/>

?:
>>></td>
>>><td>
>>>>Größe von Objekten

Zugriffsoperator (Strukturen, Unions, Klassen) <br/>
Zugriffsoperator für Elementzeiger <br/>

Bereichsoperator<br/>

Auswahloperator
>>></td>
>></tr>
</table>
Operatoren, die nur als Methoden überladen werden können

<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Operator
>>></td>
>>><td>
>>>>Bedeutung

>>></td>
>></tr>
>><tr>
>>><td>
= <br/>

[ ] <br/>

( ) <br/>

-> <br/>

(Typ)

>>></td>
>>><td>

Zuweisung <br/>

Indizierung <br/>

Funktionsaufruf bzw. Funktionsoperator <br/>

Elementzugriff für Zeiger <br/>

Typumwandlungsoperator
>>></td>
>></tr>
</table>
## 4.2. Symmetrie der Operatoren
#### Symmetrische Operatoren

Einige binäre Operationen z.B. Addition sind kommutativ und ihre beide Operanden sind &#8222;gleichberechtigt&#8220;.

**Beispiel**:
Bruch a, b, c;
c=a+b;
c=b+a;


#### Gemischte Datentypen

Die Verwendung der Operanden vom Datentyp int soll auch möglich sein.

**Beispiel**:
Bruch a, b, c;
c=a+5;
c=5+a;

#### Symmetrie der globalen Operatorfunktionen

a) Ohne Konvertierungskonstruktor
Um gemischte Datentypen zu erlauben, kann man noch zwei globalen Operatorfunktionen entwerfen:

>> Bruch operator+(Bruch a, Bruch b);
>> Bruch operator+(Bruch a, long b);
>> Bruch operator+(long a, Bruch b);

b) Mit Konvertierungskonstruktor
Der Compiler konvertiert implizit den aktuellen
Parameter vom Typ long in Typ Bruch.

>> Bruch operator+(Bruch a, Bruch b);
>> Bruch (long x);

&rArr; Demo 8.
#### Asymmetrie der Operatormethode

Die Symmetrie geht verloren, wenn die Operatorfunktion als Methode implementiert wird.

**Beispiel**: Addition einer rationalen und einer ganzen Zahl
<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Aufruf
>>></td>
>>><td>
>>>>Operatormethode
>>></td>
>></tr>
>><tr>
>>><td>
>>> c = a + 3; <br/>
c = a.operator+(3);

>>></td>
>>><td>
>>>>Bruch Bruch::operator+(int x);
>>></td>
>></tr>
>><tr>
>>><td>
>>> c = 3 + b; <br/>
c = 3 .operator+(b);

>>></td>
>>><td>
>>>>unmöglich
>>></td>
>></tr>
</table>
Wenn die Symmetrie erhalten bleiben soll, dann ist den Operator als globale Funktion zu implementieren.

## 4.3. Einzelne Operatoren
#### Shift-Operatoren

In der iostream -Bibliothek wird der Links-Shift-Operator << als ein Ausgabeoperator und der Rechts-Shift-Operator >>
als ein Eingabeoperator interpretiert.
Um die iostream- Bibliothek für die Ein- und Ausgabe von Objekten des benutzerdefinierten Datentyps zu verwenden, sollen diese Operatoren überladen werden.

#### Globale Operatorfunktion oder Operatormethode

<table class="data" width="80%" style="border:0">
>><tr>
>>><td>
>>>>Aufruf
>>></td>
>>><td>
>>>>Ersetzung durch
>>></td>
>>><td>
>>>>Zusammenfassung
>>></td>
>></tr>
>><tr>
>>><td rowspan="2">
>>>>
Bruch c; <br/>
coutc;
>>></td>
>>><td>
>>>>cout.operator(c);
>>></td>
>>><td>
>>>>Diese Methode ist nicht
implementiert
>>></td>
>></tr>

>><tr>
>>><td>
>>>>operator(cout, c);
>>></td>
>>><td>
>>>>Die globale Fkt. ist die
einzige Möglichkeit
>>></td>
>></tr>
</table>
**Rückgabe per Referenz für die Verkettung**
<table class="data" style="border:0">
>><tr>
>>><td>
>>>>#include <iostream.h> <br/>

Bruch a; <br/> cout&#8220;a= &#8220;aendl;
>>
>>></td>
>></tr>
>><tr>
>>><td>
>>>>ostream & operator (ostream & os, const Bruch & a) <br/>
{ ... <br/>
>> return os; <br/>
}
>>></td>
>></tr>
</table>
&rArr; Demo 9
#### Implementierung globaler Operatorfunktion

Ohne der Freundschaftserklärung müssen die zusätzliche öffentliche Zugriffsmethoden vorhanden sein und in der globalen Funktion aufgerufen werden.
%%(cpp)
class Bruch
{ private: long za, ne; _za-Zaehler, ne-Nenner
>>public: long getZa(){return za;}
>>>>> long getNe(){return ne;}
};
ostream & operator(ostream & out, const Bruch & b);

ostream & operator(ostream & out, const Bruch & b)
{ outb.getZa()"/"b.getNe();
>>return out;
}
%%
#### Globale Operatorfunktion als friend-Funktion
Damit eine globale Operatorfunktion direkt auf private Attribute zugreifen kann, wird sie als friend-Funktion deklariert.
%%(cpp)
class Bruch
{ private: long za, ne;_ za-Zaehler, ne-Nenner
>>friend
>>ostream & operator(ostream & out, const Bruch & b);
};

ostream & operator(ostream & out, const Bruch & b)
{ outb.za<<"/"b.ne;
>> return out;
}

%%
&rArr; Demo 10.
#### Index-Operator

Für eingebauten Datentypen dient der Index-Operator normalerweise dem Zugriff auf Feldelemente, z.B.:
>>
short a, b[2];
b[1]=5;
a=b[1];

Im Ausdruck b[i] ist b der linke Operand und i der rechte Operand. Der rechte Operand heißt Index.

Für den nicht überladenen Index-Operator gelten folgende Einschränkungen:
>>1) Der linke Operand muß ein Zeiger oder ein Feldname sein.
>>2) Der rechte Operand muß ein ganzzahliger Ausdruck sein.
>>3) Der Ausdruck b[i] impliziert eine versteckte Zeigerarithmetik: *(b + i)
#### Index-Operator für eine Klasse

Für eine Klasse muss ein Index-Operator als Methode überladen werden.
>>
>> %%(cpp)
class Array
>> { public: float & operator[](int i);
>> }; %%

Für den überladenen Index-Operator gelten folgende Einschränkungen:
>>1) Der linke Operand muß ein Objekt der Klasse sein.
>>2) Der rechte Operand darf einen beliebigen Datentyp haben.
>>3) Der Ergebnis-Typ ist nicht festgelegt.
>>4) Das Ergebnis soll eine Referenz auf ein Objekt sein.

&rArr; Demo 11.
#### Zuweisungsoperator

Ein existierender Objekt wird durch eine Kopie eines anderen ersetzt.

Für jede Klasse ist ein Standard-Zuweisungsoperator implizit vordefiniert. Die Standardzuweisung erfolgt elementweise: d.h. für jedes Attribut des Objektes wird der entsprechende Zuweisungsoperator aufgerufen.

Der Zuweisungsoperator für Grunddatentypen bewirkt eine bitweise Kopie.


Wenn eine Klasse dynamische Attribute enthält, muß für diese Klasse ein expliziter (statt impliziter) Zuweisungsoperator überladen werden. Ein Zuweisungsoperator kann nur als eine Operatormethode überladen werden:

%%(cpp)
class Array
>>{ public: Array & operator=(const Array & neu);
>>}; %%

Es gibt zwei Formulierungen für den Aufruf:
%%(cpp)
>> Array a, b;
>> a = b; _impliziter Aufruf
>> a.operator=(b);_ expliziter Aufruf
%%
Ein Zuweisungsoperator soll immer das Objekt, für das der Operator aufgerufen wurde, als Referenz zurückliefern. Dies ermöglicht verkettete Zuweisungen.
>> Array a, b, c; a = b = c;

Im Zuweisungsoperator sollte getestet werden, ob ein Objekt sich selbst zugewiesen wird. Dies ermöglicht so genannter &#8222;Zuweisung an sich selbst&#8220;.
%%(cpp)
Array a; a = a;

>> Array & Array::operator=(const Array & neu)
>> { if(this
##### & neu) return *this;
>>>> . . .
>>>> return *this;
>> } %%
>>
Der Zuweisungsoperator ist im Prinzip eine Kombination aus Destruktor und Kopierkonstruktor.

%%(cpp)
typedef ... T;
class Array
{ private: T* z; int n;
>> public:
>>> Array & operator=(const Array & neu)
>>> { if(this & neu) return *this;
>>>> delete[] z; _alten Speicher freigeben
>>>> n=neu.n; z=new T[n];_ neuen reservieren
>>>> for(int i=0; i<n; i++) z[i]=neu.z[i]; _Kopie
>>>> return *this;
>>> }
};
%%

&rArr; Demo 12.
Auch der Funktionsaufruf ist ein Operator, der für eigene Klassen definiert werden kann.

**Synonyme**: Funktionsoperator, Klammeroperator, operator(), Funktionsaufrufoperator.

Im folgenden Prinzipbeispiel wird ein parameterlose unktionsoperator deklariert:

class XXX
{ &#8230;
>>public: void operator() ();
};

Ein Objekt mit der Funktionsoperator wird Funktionsobjekt der Funktor benannt. Die Funktionsobjekte werden in der C++-Standardbibliothek verwendet.

Der Funktionsoperator bringt überraschende Konsequenzen: ein Funktionsobjekt kann wie eine Funktion aufgerufen werden:
Es sieht so aus, als würde eine globale Funktion x1() aufgerufen. Tatsächlich wird der Funktionsoperator des Objektes x1 aufgerufen.
![image](/uploads/ObjProg04Operator/oop16.gif?width=200)
Der explizite Aufruf des Funktionsoperators ist syntaktisch ebenfalls erlaubt:
![image](/uploads/ObjProg04Operator/oop17.gif?width=200)
Die Funktionsobjekte können wie andere Methoden mehrfach überladen werden, z.B.:
%%(cpp)
class Polynom
{ float a, b, c;
public:
>> Polynom(float aa, float bb, float cc){a=aa; b=bb; c=cc;}
>> float operator( )(float x){ return a*x*x + b*x + c; }
>> float operator( )(float a, float b, float c, float x)
>> { return a*x*x + b*x + c;_ Funktionswert
>> }
};
int main()
{ Polynom po(5, 6, 7);
>> cout po(3)&#8220; &#8220;po(3, -2, -7, 5); _70 58
} %%
Ein wichtiger Vorteil ist, dass ein Funktionsobjekt statt Funktionszeiger als Parameter zu einer Funktion übergeben werden könnte. Das ist die objektorientierte Alternative.
**Beispiel**:

%%(cpp)
double Doppelt (Polynom p, float x)
>> { return 2*p(x);
>> }
>> int main()
>> { Polynom po(5, 6, 7);
>>>> cout Doppelt(po, 3)" &#8220;
>>>>>> Doppelt(Polynom(3, -2, -7), 5);_ 140 116

>> } %%

&rArr; Demo 13, 14.
## 4.4. Iterator-Operatoren
#### Behälter und Iterator

Ein <span style="text-decoration:underline;">Behälter </span>(container oder collection) ist ein Objekt, das zum Verwalten von anderen Objekten (Elementen) dient.

Jedes Element in einem Behälter besitzt eine bestimmte <span style="text-decoration:underline;">Position</span>, in der es abgelegt ist. Man kann über die Position direkt auf das einzelne Element zugreifen. Die Darstellung der Position ist von der Implementierung des Behälters abhängig. Zeiger und Indexe sind bekannte Bespiele dafür.

Ein <span style="text-decoration:underline;">Iterator </span>ist ein Objekt, das eine Position in einem Behälter repräsentiert (verweist, zeigt). Ein Iterator dient dazu, von den Implementierungsdetails des Behälters zu abstrahieren. Begriffsverwirrung: Mit dem Begriff &#8222;Iterator&#8220; können auch eine Klasse und ein Konzept bezeichnet werden.
**Prinzipbeispiel**:
![image](/uploads/ObjProg04Operator/oop18.gif?width=500)
#### Iterator-Operatoren

1. **Operatoren**zum Iterieren (Durchwandern). Die Position, welche durch einen Iterator repräsentiert wird, wird zur Position des nächsten (oder vorigen) Elementes im Behälter gewechselt. Beispielsweise wechselt ein Inkrement-Operator++ auf Position des nächsten Elementes.

2. **Vergleichsoperatoren**. Zwei Iteratoren können verglichen werden, z.B. der Gleich-Operator
##### liefert true, wenn zwei Iteratoren auf dasselbe Element verweisen.
!= < > <= >=

3. **Zugriffsoperatoren**. Das Element, welches durch einen Iterator repräsentiert wird, wird gelesen oder geändert (überschrieben). Beispiel: ein Inhalts-Operator* des Iterators liefert die Referenz auf das repräsentierten Element.
* -> [ ]
DELETIONS
a*b; x*y; //verschiedene Algorithmen
Revision [e4ea8c5]
Die älteste bekannte Version dieser Seite wurde von RonnyGertler am 2013-03-28 23:58:10 erstellt
ADDITIONS
![image](/uploads/ObjProg04Operator/BMBF_Logo_klein.jpg?width=200)
# Objektorientierte Programmierung - Kapitel 4 - Operator - Überladung
_<span class="right">Inhalte von Dr. E. Nadobnyh</p>_
## 4.1. Grundlagen und Regeln
#### Operator-Überladung

Ein Operator ist überladen, wenn er je nach Typ der Operanden eine unterschiedliche Bedeutung hat.

Die meisten Operatoren für eingebauten Datentypen sind schon überladen.

**Beispiel**:

double a, b; short x, y;

a*b; x*y; //verschiedene Algorithmen

#### Operatorfunktion

In C++ gibt es die Möglichkeit , Operatoren für die Klassen zu definieren.

Eine Operatorfunktion ist eine Funktion mit einem besonderen Namen. Der Name der Operatorfunktion beginnt mit dem Schlüsselwort <span style="color:blue;">operator</span>, dem das Operatorsymbol folgt. Ausdrücke mit Operatoren sind intuitiver und daher schneller zu erfassen als Ausdrücke mit Funktionsaufrufe.
#### Zwei Definitionsmöglichkeiten

Eine Operatorfunktion kann entweder als globale Funktion oder als Methode einer Klasse definiert werden.

**1) Globale Operatorfunktion**

>> class Bruch{ };
>> Bruch operator+ (Bruch, Bruch );
>>
**2) Operatormethode**
>>bzw. Operatorfunktion als Methode

>> class Bruch
>> { public:
>>>>Bruch operator+ (Bruch x);
>> };
***
CategoryObjProg