ich war hier: ObjProg04Operator

Revision history for ObjProg04Operator


Revision [83271]

Last edited on 2017-08-16 15:16:50 by ClaudiaMichel
Additions:
CategoryObjektorientierteProgrammierung
Deletions:
CategoryDelete


Revision [72100]

Edited on 2016-09-27 12:42:05 by NicoleHennemann
Additions:
CategoryDelete
Deletions:
CategoryObjProg


Revision [26598]

Edited on 2013-04-29 18:53:07 by RonnyGertler
Additions:
2) Ein Inkrement-Operator schiebt den Iterator auf die nächste Position: "" s++; ""
===Inhalts-Operator===
Der Inhaltsoperator * (Dereferenzierungsoperator, Verweisoperator, Indirektionsoperator) liefert eine Referenz auf das Element, an dessen Position sich der Iterator befindet.
**Prinzipbeispiel: **
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:**
typedef … 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**
class Behaelter
{ struct KN{ ...; KN* next;};
public:
class iterator
{ KN* c; //Zeiger auf aktuellen Knoten
public:
iterator & operator++() { c = c->next; return *this;}
};
}; %%
Deletions:
2) Ein Inkrement-Operator schiebt den Iterator auf die nächste Position: s++;


Revision [26597]

Edited on 2013-04-29 18:48:24 by RonnyGertler
Additions:
{{image url="oop19.gif" width="500"}}
===Anwendung von Iteratoren===
1) Die Verbindung zwischen Behälter und Iterator wird mit den Methoden „start“ und „ende“ 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 url="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:**
main()
{
Behaelter b; //Behaelter-Definition
Behaelter::iterator i; //Iterator-Definition
for (i=b.start( ); i!=b.ende( ); ++i)
cout<<*i<<" ";
}
⇒ Demo 13
Deletions:
class Behaelter
{
class iterator
{ public: //Operatoren
bool operator!=(iterator i); //Ungleich
T& operator*(); //Inhalt
iterator operator++(); //Inkrement

iterator start();
iterator ende();


Revision [26594]

Edited on 2013-04-29 18:44:18 by RonnyGertler
Additions:
===Iterator als geschachtelte Klasse===
**Prinzipbeispiel**
typedef … T; //Typ des Elementes
class Behaelter
{
class iterator
{ public: //Operatoren
bool operator!=(iterator i); //Ungleich
T& operator*(); //Inhalt
iterator operator++(); //Inkrement

iterator start();
iterator ende();


Revision [26593]

Edited on 2013-04-29 18:39:57 by RonnyGertler
Additions:
2. **Vergleichsoperatoren**. Zwei Iteratoren können verglichen werden, z.B. der Gleich-Operator""=="" liefert true, wenn zwei Iteratoren auf dasselbe Element verweisen.
Deletions:
2. **Vergleichsoperatoren**. Zwei Iteratoren können verglichen werden, z.B. der Gleich-Operator== liefert true, wenn zwei Iteratoren auf dasselbe Element verweisen.


Revision [22782]

Edited on 2013-03-29 00:58:52 by RonnyGertler
Additions:
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.
Deletions:
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.


Revision [22781]

Edited on 2013-03-29 00:54:21 by RonnyGertler
Additions:
{{image url="oop16.gif" width="200"}}
{{image url="oop17.gif" width="200"}}
===Behälter und Iterator ===
Ein __Behälter __(container oder collection) ist ein Objekt, das zum Verwalten von anderen Objekten (Elementen) dient.
Jedes Element in einem Behälter besitzt eine bestimmte __Position__, 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 __Iterator __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 „Iterator“ können auch eine Klasse und ein Konzept bezeichnet werden.
**Prinzipbeispiel**:
{{image url="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:
{{image url="oop16" width="200"}}
{{image url="oop16" width="200"}}


Revision [22780]

Edited on 2013-03-29 00:50:19 by RonnyGertler
Additions:
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
}
};
%%
""⇒"" 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
{ …
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 url="oop16" width="200"}}
Der explizite Aufruf des Funktionsoperators ist syntaktisch ebenfalls erlaubt:
{{image url="oop16" width="200"}}
Die Funktionsobjekte können wie andere Methoden mehrfach überladen werden, z.B.:
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)<<“ “<<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.
%%(cpp)
double Doppelt (Polynom p, float x)
{ return 2*p(x);
}
int main()
{ Polynom po(5, 6, 7);
cout<< Doppelt(po, 3)<<" “
<< Doppelt(Polynom(3, -2, -7), 5); // 140 116
} %%
""⇒"" Demo 13, 14.
=====4.4. Iterator-Operatoren =====


Revision [22779]

Edited on 2013-03-29 00:45:02 by RonnyGertler
Additions:
===Globale Operatorfunktion als friend-Funktion===
Damit eine globale Operatorfunktion direkt auf private Attribute zugreifen kann, wird sie als friend-Funktion deklariert.
{ private: long za, ne; //za-Zaehler, ne-Nenner
friend
ostream & operator<<(ostream & out, const Bruch & b);
{ out<<b.za<<"/"<<b.ne;
return out;
%%
""⇒"" 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.
""⇒"" 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:
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 „Zuweisung an sich selbst“.
Array a; a = a;
Array & Array::operator=(const Array & neu)
{ if(this== & neu) return *this;
. . .
return *this;
} %%


Revision [22778]

Edited on 2013-03-29 00:39:36 by RonnyGertler
Additions:
**Rückgabe per Referenz für die Verkettung**
""<table class="data" style="border:0">
#include <iostream.h> <br/>
Bruch a; <br/> cout<<“a= “<<a<<endl;

ostream & operator<< (ostream & os, const Bruch & a) <br/>
{ ... <br/>
return os; <br/>
}
""⇒"" 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.
{ 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)
{ out<<b.getZa()<<"/"<<b.getNe();
return out;
%%


Revision [22777]

Edited on 2013-03-29 00:36:56 by RonnyGertler
Additions:
Bruch Bruch::operator+(int x);
unmöglich
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 ===
Aufruf
Ersetzung durch
Zusammenfassung
<td rowspan="2">

Bruch c; <br/>
cout<<c;
cout.operator<<(c);
Diese Methode ist nicht
implementiert

operator<<(cout, c);
Die globale Fkt. ist die
einzige Möglichkeit
Deletions:
Bruch Bruch::operator+(int x); <br/>
<br/>
unmöglich <br/><br/>


Revision [22776]

Edited on 2013-03-29 00:33:18 by RonnyGertler
Additions:
===Symmetrische Operatoren ===
Einige binäre Operationen z.B. Addition sind kommutativ und ihre beide Operanden sind „gleichberechtigt“.
**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);
""⇒"" Demo 8.
===Asymmetrie der Operatormethode===
Die Symmetrie geht verloren, wenn die Operatorfunktion als Methode implementiert wird.
**Beispiel**: Addition einer rationalen und einer ganzen Zahl
Aufruf
Operatormethode
c = a + 3; <br/>
c = a.operator+(3);
Bruch Bruch::operator+(int x); <br/>
<br/>
c = 3 + b; <br/>
c = 3 .operator+(b);
unmöglich <br/><br/>


Revision [22775]

Edited on 2013-03-29 00:29:38 by RonnyGertler
Additions:
Eine Definition von neuen Operatoren ist nicht möglich, z.B. neuen Operator ""**"" zum Potenzieren. Andere Zeichen wie $ usw. sind nicht erlaubt.
Operatoren, die nur als Methoden überladen werden können
= <br/>
[ ] <br/>
( ) <br/>
-> <br/>
(Typ)
Zuweisung <br/>
Indizierung <br/>
Funktionsaufruf bzw. Funktionsoperator <br/>
Elementzugriff für Zeiger <br/>
Typumwandlungsoperator
=====4.2. Symmetrie der Operatoren =====
Deletions:
{{files}}
Eine Definition von neuen Operatoren ist nicht möglich, z.B. neuen Operator ** zum Potenzieren. Andere Zeichen wie $ usw. sind nicht erlaubt.


Revision [22774]

Edited on 2013-03-29 00:27:31 by RonnyGertler
Additions:
""⇒"" Demo 4. "" C++"" Operatoren
4) Wenigstens ein Argument der Operatorfunktion muss ein class –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.
""⇒"" 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.)
""⇒"" 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>
""
Deletions:
""⇒"" Demo 4. C++ Operatoren


Revision [22773]

Edited on 2013-03-29 00:20:22 by RonnyGertler
Additions:
===Operatormethode===
{ public: Bruch operator+(Bruch b);
{ 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.
""⇒"" 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.

""⇒"" Demo 4. C++ Operatoren


Revision [22772]

Edited on 2013-03-29 00:17:46 by 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 url="oop15.gif" width="450"}}
===Mehrdeutigkeit ===
Wenn Compiler mehr als eine Aufrufmöglichkeit findet, wird der Aufruf bemängelt.
""⇒"" 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
}
%%
""⇒"" Demo 1.2
Deletions:
a*b; x*y; //verschiedene Algorithmen


Revision [22771]

Edited on 2013-03-29 00:14:01 by RonnyGertler
Additions:
{{files}}


Revision [22770]

The oldest known version of this page was created on 2013-03-28 23:58:10 by RonnyGertler
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki