Stand: 26. Juni 2015
Inhalt 1 2 3
Übersicht 1 2 3
Warum Operatoren überladen? Großteil der Operatoren (Arithmetik, Logik, Vergleiche) nur für Standarddatentypen (Zahlen, Zeiger) implementiert vergleichbare Funktionalität muss für komplexe Datentypen (Strukturen, Objekte) über Funktionen gelöst werden Funktionsrufe teils weniger intuitiv, komplexere Anweisungen Operatoren können Funktionalität verständlicher ausdrücken
Übersicht 1 2 3
Was bedeutet Überladung? es existieren mehrere Funktionen mit gleichem Namen (die selbes Problem lösen) Funktionen unterscheiden sich durch Typ und/oder Anzahl der Parameter Rückgabetypen können verschieden sein, aber: verschiedene Rückgabetypen bei gleicher Parameterliste funktioniert nicht! jede Funktion auf Parameter angepasste Umsetzung Effekt: selber Name bezeichnet spezielle Realisierung für verschiedene Typen von Parametern Kompiler wählt bei Übersetzung passende Funktion aus
Beispiel I #include <iostream> using namespace std ; struct vec3 { double x,y, z; }; vec3 vmul(vec3 vektor, int skalar ){ vec3 result ; cout<< Multiplikation mit Integer <<endl ; result.x = vektor.x skalar ; result.y = vektor.y skalar ; result. z = vektor. z skalar ; return result ; } vec3 vmul(vec3 vektor, double skalar ){
Beispiel II } vec3 result ; cout<< Multiplikation mit Double <<endl ; result.x = vektor.x skalar ; result.y = vektor.y skalar ; result. z = vektor. z skalar ; return result ; double vmul(vec3 vektor1, vec3 vektor2){ cout<< Skalarprodukt <<endl ; double sp ; sp = vektor1.x vektor2.x; sp += vektor1.y vektor2.y; sp += vektor1. z vektor2. z; return sp ; } int main(){
Beispiel III vec3 v1, v2 ; double sp ; v1.x = 1.0; v1.y = 1.5; v1. z = 0.6; v2.x = 0.3; v2.y = 0.7; v2. z = 2.0; vmul(v1,2); vmul(v2,1.5); sp = vmul(vmul(v1,2), v2 ); cout<< Vektor1: <<v1.x<<, <<v1.y<<, <<v1.z<<endl ; cout<< Vektor2: <<v2.x<<, <<v2.y<<, <<v2.z<<endl ; cout<< Skalarprodukt : <<sp<<endl ; } return 0;
Welche Operatoren sind überladbar? I Fast alle Operatoren können überladen werden: Arithmetik: +,,, /, % (Divisionsrest - Modulo) Zuweisung: = Inkrement/Dekrement: ++, Vergleiche: ==,!=, >, <, >=, <= Elementzugriff: [] kombinierte Operation und Zuweisung: +=, =, =, /=, %=, &=, =, ˆ=, <<=, >>= Schiebeoperator: << (Ausgabe bzw. bitweise Verschiebung), >> (Eingabe bzw. bitweise Verschieb Logik: &&,,! (Nicht) Bitoperationen: ˆ (XOR), (OR), & (AND), (Komplement)
Welche Operatoren sind überladbar? II Typkonvertierungen Auch möglich, aber selten genutzt (und teils komplex): Funktionsruf: () Referenz, Dereferenz, Pfeiloperator: &,, > Komma:, dynamischer Speicher: new, new[], delete, delete[]
Umsetzung I allgemein: Schlüsselwort operator gefolgt von zu überladendem Operator bei Operatoren für dynamischen Speicher und Typkonvertierungen mit Leerzeichen zwischen operator und Operator (z.b. operator new(std:: size t size)) bei Typkonvertierungen: kein Rückgabetyp!
Operatortypen I Zwei Typen werden unterschieden: unäre Operatoren (@x bzw. x@), arbeiten auf nur einer Variablen: ohne Argument: Inkrement/Dekrement (Präfix - ++i), Nicht, Komplement, Referenz, Dereferenz, Pfeiloperator, Typkonvertierungen mit einem Argument: Inkrement/Dekrement (Postfix - i ++), Elementzugriff, dynamischer Speicher mit beliebiger Anzahl Argumente: Funktionsruf binäre Operatoren (x@y), arbeiten auf zwei Variablen: alle anderen
Operatortypen II Argumente unärer Operatoren: Postfix Inkrement/Dekrement: Integer Pseudoargument, um Unterscheidung von Präfixoperator zu ermöglichen Elementzugriff: Integer, angegebener Index dynamischer Speicher: new, new[]: std:: size t, Größe des anzulegenden Elements in Byte delete, delete []: void, Zeiger auf freizugebendes Element Funktionsruf: Funktionsparameter
Freunde Klassen können Freunde haben, die auf private (auch protected) Elemente zugreifen dürfen Freunde können andere Klassen oder Funktionen sein Freundschaft ist einseitig: wenn Klasse B Freund von Klasse A ist, muss dies nicht umgekehrt auch so sein! Definition von Freunden in Klassendefinition mit Schlüsselwort friend plus Name Klasse/Funktion, welche Freund sein soll
Übersicht 1 2 3
Definition der Operatorfunktionen I Operatorfunktionen können global oder als Klassenmethode definiert werden falls für ein Objekt global und als Klassenmethode vorhanden wird Klassenmethode verwendet! Aufbau global: Operanden als erste Parameter unäre Operatoren: <Rtyp> operator@(<typx> x) binäre Operatoren: <Rtyp> operator@(<typx> x,<typy> y) Aufbau Klassenmethode von TypX: unäre Operatoren: <Rtyp> operator@(), Methode wird auf x aufgerufen binäre Operatoren: <Rtyp> operator@(<typy> y), Methode wird auf x aufgerufen
Definition der Operatorfunktionen II Einschränkungen/Anmerkungen: für einige Operatoren nur als Klassenmethode möglich: Zuweisung, Elementzugriff, Funktionsruf, Pfeiloperator Verschiebeoperatoren für Ein- und Ausgabe können nicht als Klassenmethoden implementiert werden für die meisten Operatoren Definition als Klassenmethode sinnvoll, da meist Zugriff auf private Elemente Reihenfolge wichtig: für x@y kann andere Funktion erforderlich sein als für y@x! falls x Standarddatentyp nur globale Funktion möglich! arithmetische und logische Operatoren sollten Element mit berechneten Werten zurück geben, um Verkettung von Operatoren zu erlauben
Definition der Operatorfunktionen III Objekte sollten als Referenz übergeben werden, um implizite Kopien zu vermeiden Referenzparameter, die von Funktion nicht verändert werden, sollten mit const markiert werden teilt Kompiler mit, dass sie nicht verändert werden, kann Probleme vermeiden
Beispiel Aufgrund des Umfangs separat als Quellcode verfügbar: operatoren.cpp