Wenn Klassenoperationen
natürlich aussehen
Funktionsnamen können
überladen werden, d.h. nach Typ und Anzahl der Parameter und Rückgabetyps
Warum nicht auch alle definierten Operatorsymbole überladen?
Notwendig dazu:
Neuimplementierung von
Operatoren als überladbare
Funktionen
<Typ> operator⊗(<Param_Liste>);
bzw
<Typ> <Klassenname>::operator⊗(<Param_Liste>) {<Funktionsrumpf>
}
Man achte auf die Syntax!
Das Symbol ⊗ ist der zu überladende Operator
<Typ> ist meistens der Klassentyp
Die natürliche Operatorpräzedenz darf nicht geändert werden
Anzahl der Parameter darf nicht geändert werden, z. B. binäre
Operatoren bleiben binäre Operatoren
Operatoren können auch mit const
überladen werden
Operatoren sollten ihre
prädefinierte Bedeutung auch für neue Operationen beibehalten
Keine mehrdeutigen Operatoren, d.h. Operatoren mit mehreren
Interpretationen
Immer nach Schnittstellendefinition passende Operatoren suchen, z.B.
copy() wird Zuweisungsoperator
Überladene mehrfache Operatoren werden nicht automatisch aus
ihren überladenen Komponenten definiert
Z.B. += setzt sich nicht aus + und
= zusammen
Wenn solche Operatoren
überladen werden, dann auch
konsequent
! "
class Vektor{
private:
double x,y,z;
public:
Vektor(){}
Vektor(double a, double b, double c) : x(a), y(b), z(c) {}
void setX(double a){x = a;}
void setY(double b){y = b;}
void setZ(double c){z = c;}
Vektor operator+(const Vektor &);
Vektor operator-(const Vektor &);
Vektor operator&(const Vektor &);
Vektor& operator=(const Vektor &);
# !
#include "Vektor.h"
Vektor Vektor::operator+(const Vektor & op2) {
Vektor temp;
temp.x = x + op2.x; //oder (*this).x + op2.x temp.y = y + op2.y;
temp.z = z + op2.z;
return temp;
}
Vektor Vektor::operator-(const Vektor & op2) {
return Vektor(x - op2.x, y - op2.y, z - op2.z);
# ! $ %
Vektor Vektor::operator&(const Vektor & op2) {
Vektor temp;
temp.x = y*op2.z - z*op2.y;
temp.y = z*op2.x - x*op2.z;
temp.z = x*op2.y - y*op2.x;
return temp;
}
Vektor& Vektor::operator=(const Vektor & rhs) {
if (this != &rhs){
x = rhs.x; y = rhs.y;
z = rhs.z;}
return *this;
Zuweisungsoperator gibt Objekt des Typs Vektor zurück!
Grund: Mehrfache Zuweisungen, wie
v1 = v2 = v3;müssen möglich sein
Der Zuweisungsoperator wird immer defaultmässig vom
Compiler zur Verfügung gestellt
&
#include "Vektor.h"
int main(void) {
Vektor v1(1,0,0), v2(0,1,0),v3,v4;
v3 = v1 + v2;
v4 = v1 & v2;
return 0;
}
friend ' (
Entwurfsprinzip: Überladener <<
Operator hat ersten Operanden als
ostream , zweiter Operand ist das
auszugebende Klassenobjekt und
der Rückgabetyp ist ein ostream
Konsequenz: << kann nicht als
Klassenfunktion implementiert
werden!
) *
Die Ein- und Ausgabeoperatoren
>> und << können als friend - Funktionen der zugrundliegenden Klasse definiert werden
Wegen Assoziativität soll (eine
Referenz auf) einen iostream
zurückgegeben werden
( + Vektor
class Vektor{
private:
double x,y,z;
public:
friend ostream & operator<<(ostream &, Vektor&);
friend istream & operator>>(istream &, Vektor&);
...
};
# (
ostream & operator<<(ostream &stream, Vektor &v) {
stream << "(" << v.x << "," << v.y << "," << v.z << ")";
return stream;
}
istream & operator>>(istream &stream, Vektor &v) {
cin >> v.x;
cin >> v.y;
cin >> v.z;
return stream;
}
Bei Eingabe: Fehlerprüfung. Falls Fehler
stream.setstate(ios_base::failbit);
Lese- und Schreiboperationen haben keine Wirkung im
Fehlerzustand! Lösung: immer
stream testen!
&
#include "Vektor.h"
int main(void) {
Vektor v1(1,0,0), v2(0,1,0), v3;
cout << v1 << " + " << v2 << " = ";
v3 = v1 + v2;
cout << v3 << endl;
return 0;
}
Ausgabe:
(1,0,0) + (0,1,0) = (1,1,0)