kennen:operator
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | kennen:operator [2020-07-27 09:55] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Operatoren ====== | ||
+ | > Ausdrücke sind eine Folge von Operatoren und Operanden, die eine Berechnung bewirken. Ausdrücke können einen Wert ergeben und können Nebenwirkungen (Seiteneffekte) hervorrufen. | ||
+ | >> | ||
+ | |||
+ | |||
+ | C und C++ sind reich an Operatoren. | ||
+ | Nicht alle sind unmittelbar einsichtig, u.a. deshalb wirkt C so kryptisch auf Sprachfremde. | ||
+ | Operatoren werden auf Operanden (Variablen, Konstanten, Ausdrücke) angewendet und verknüpfen diese: | ||
+ | <code cpp> | ||
+ | punkte[mannschaft] += gewonnen ? 2 : 0 | ||
+ | (c=getchar()) != EOF | ||
+ | (*d++ = *s++) != 0 | ||
+ | </ | ||
+ | |||
+ | Die [[# | ||
+ | Die Verknüpfung geschieht in einer bestimmten | ||
+ | [[# | ||
+ | Bei arithmetischen Ausdrücken wie | ||
+ | <code cpp> | ||
+ | x = 2.1 + 3*4/5 - 6.3 | ||
+ | </ | ||
+ | erfolgt Punktrechnung vor Strichrechnung (höherer Rang). | ||
+ | Die rechte Seite (Rechtswert, | ||
+ | muss vollständig berechnet sein, | ||
+ | ehe deren Wert an die links stehende Variable (Linkswert, lvalue) zugewiesen wird. | ||
+ | Die Änderung eines gespeicherten Variablenwertes ist ein Seiteneffekt. | ||
+ | Leerzeichen neben den Operatoren ändern die Bedeutung nicht, | ||
+ | können aber die Lesbarkeit des Quelltextes erhöhen. | ||
+ | |||
+ | Der Wert von 12/5 ist nicht 2.4, sondern die Ganzzahl 2, da beide Operanden ganzzahlig sind. | ||
+ | 12.0/5 ergibt hingegen 2.4 als gebrochene Zahl, genauer: einen Wert, der dieser Zahl möglichst nahe kommt. | ||
+ | |||
+ | Die [[# | ||
+ | (Assoziativität) legt fest, | ||
+ | in welcher Richtung gleichrangige Operationen gruppiert werden: | ||
+ | <code cpp> | ||
+ | z = 10 - 5 - 2 | ||
+ | </ | ||
+ | wird linksassoziativ als '' | ||
+ | Klammern erzwingen eine Gruppierung: | ||
+ | <code cpp> | ||
+ | std::cout << (2<=3) << ' | ||
+ | </ | ||
+ | Nur wenige Operatoren erzwingen eine bestimmte Auswertefolge der Teilausdrücke. | ||
+ | Compiler können | ||
+ | <code cpp> | ||
+ | i = 1; | ||
+ | a[i] = i++; | ||
+ | </ | ||
+ | unterschiedlich auswerten: Es kann '' | ||
+ | Ab [[begriffe# | ||
+ | Alle Seiteneffekte rechts der Zuweisung werden zuerst ausgewertet. | ||
+ | Dennoch ist es schlechter Programmierstil, | ||
+ | )) | ||
+ | |||
+ | |||
+ | ===== Rangfolge ===== | ||
+ | > Effektives Schreiben (oder Lesen) in C ohne Kenntnis dieser Regeln ist unmöglich. Bitte studiere die Rangtabelle jeden Abend beim Zähneputzen. | ||
+ | >> ---[ [[http:// | ||
+ | |||
+ | |Rang|Bindung|Zweck|Operator| | ||
+ | |1|L| [[# | ||
+ | |2|L| Postfix-Inkrement/ | ||
+ | |3|R| Präfix-Inkrement/ | ||
+ | |4|L| [[# | ||
+ | |5|L| [[# | ||
+ | |6|L| [[# | ||
+ | |7|L| [[#Bitweise Operatoren|Bitschieben]]| '' | ||
+ | |8|L| [[kennen: | ||
+ | |9\\ 10|L| [[# | ||
+ | |11\\ 12\\ 13|L| [[#Bitweise Operatoren|bitweise]] UND \\ XOR \\ ODER | ''& | ||
+ | |14\\ 15|L| [[#Logische Operatoren|logisch]] UND \\ ODER| ''&& | ||
+ | |16|R| [[# | ||
+ | |17|L| [[# | ||
+ | |||
+ | | L | linksassoziativ: | ||
+ | | R | rechtsassoziativ: | ||
+ | |||
+ | |||
+ | ===== Wirkung ===== | ||
+ | ==== Bereichsauflösung ==== | ||
+ | Manche Bezeichner gehören einem bestimmten [[.: | ||
+ | oder einer Klasse an. | ||
+ | Sie werden mit '' | ||
+ | <code cpp> | ||
+ | std::cout | ||
+ | std:: | ||
+ | :: | ||
+ | </ | ||
+ | Alle Funktionen, Klassen, Objekte der Standard-Bibiothek sind im Namensbereich '' | ||
+ | Der globale Namensbereich enthält die Bezeichner außerhalb von geschweiften Klammern. | ||
+ | Der Bereichsauflösungsoperator vor '':: | ||
+ | erlaubt auf den globalen Namen zuzugreifen selbst dann, | ||
+ | wenn er durch einen lokalen gleichnamigen Bezeichner verdeckt ist. | ||
+ | |||
+ | ==== Zugriff ==== | ||
+ | Komponenten, | ||
+ | und Objekten werden mit '' | ||
+ | |||
+ | Der Ausdruck '' | ||
+ | <code cpp> | ||
+ | struct Punkt { int x, y; }; | ||
+ | Punkt a; | ||
+ | a.x = 2; | ||
+ | |||
+ | Punkt* a_ptr = &a; | ||
+ | a_ptr->y = 3; | ||
+ | </ | ||
+ | Mit eckigen Klammern wird auf das Element '' | ||
+ | eines Feldes zugegriffen (Feldoperator oder Indexoperator). | ||
+ | <code cpp> | ||
+ | int feld[10]; | ||
+ | feld[0] = 1; | ||
+ | </ | ||
+ | Runde Klammern '' | ||
+ | Als Funktionsoperator schliessen sie die Funktionsparameter (Argumente) ein. | ||
+ | <code cpp> | ||
+ | x = (2+3)*5; | ||
+ | y = sqrt(2); | ||
+ | </ | ||
+ | Die Postfix-Operatoren '' | ||
+ | [[# | ||
+ | Sie haben höheren Rang als andere [[# | ||
+ | <code cpp> | ||
+ | *d++ = *s++; // erhöht Zeiger s, nicht Wert *s | ||
+ | </ | ||
+ | Der Schlüsselwort-Operator [[.: | ||
+ | ist zur Laufzeit-Typabfrage vorgesehen. | ||
+ | <code cpp> | ||
+ | std::cout << typeid(Punkt).name() << ' | ||
+ | </ | ||
+ | ==== Einstellige Operatoren ==== | ||
+ | Die Präfix-Operatoren '' | ||
+ | sind [[# | ||
+ | Negieren kann je nach Ziel mit | ||
+ | * dem Minus-Vorzeichen '' | ||
+ | * dem Nicht-Operator '' | ||
+ | * oder dem Komplement-Operator '' | ||
+ | |||
+ | Der Adressoperator ''&'' | ||
+ | Der Inhaltsoperator '' | ||
+ | auf dessen Adresse der dahinterstehende Zeiger-Ausdruck verweist. | ||
+ | Er dereferenziert den Zeiger. | ||
+ | Adressoperator und Inhaltsoperator sind zueinander invers. | ||
+ | <code cpp> | ||
+ | int i = 1; | ||
+ | int* p = &i; | ||
+ | *p = 2; | ||
+ | </ | ||
+ | Mit den Operatoren [[.: | ||
+ | und [[.: | ||
+ | wird dynamischer Speicher angefordert bzw. wieder freigegeben. | ||
+ | <code cpp> | ||
+ | p = new int[n]; | ||
+ | // ... benutze Feld mit n int-Werten | ||
+ | delete [] p; | ||
+ | </ | ||
+ | Werden mit '' | ||
+ | muss die Freigabe mit '' | ||
+ | Bei Einzelobjekten ist weder bei '' | ||
+ | noch bei '' | ||
+ | Die Nichtbeachtung führt zu schwerwiegenden Fehlern in der Speicherverwaltung. | ||
+ | |||
+ | Der Ausdruck '' | ||
+ | |||
+ | ==== Elementzeiger ==== | ||
+ | Methodenzeiger (und Attributzeiger) '' | ||
+ | auf Methoden (Attribute) einer Struktur / Klasse | ||
+ | sind eigentlich keine Zeiger, sondern " | ||
+ | Sie ermöglichen die Auswahl einer Methode (eines Attributs), | ||
+ | ohne schon ein Objekt benennen zu müssen. | ||
+ | Die Ausführung (der Zugriff) erfolgt dann über '' | ||
+ | bzw. '' | ||
+ | ([[.: | ||
+ | |||
+ | Das Eintragen (Registrieren) von Zeigern auf Funktionen | ||
+ | für einen späteren Aufruf wird als Callback-Technik bezeichnet. | ||
+ | Diese Technik findet sich häufig in ereignisgesteuerten Programmen (Bedienoberflächen). | ||
+ | Ein solcher Callback-Mechanismus für Objekte | ||
+ | wird in der '' | ||
+ | |||
+ | ==== Arithmetische Operatoren ==== | ||
+ | Die arithmetischen Operatoren '' | ||
+ | haben die gewohnte mathematische Bedeutung, mit einer Ausnahme: | ||
+ | Das Ergebnis von '' | ||
+ | Operationen führen nicht aus dem Zahlbereich der Operanden heraus. | ||
+ | Ist mindestens ein Operand von einem gebrochenzahligen Typ ('' | ||
+ | so ist es auch das Ergebnis. | ||
+ | Sind die Typen der Operanden unterschiedlich, | ||
+ | wird vor der Operation der " | ||
+ | <code cpp> | ||
+ | std::cout << 13/5 << | ||
+ | std::cout << 13.0/5 << ' | ||
+ | </ | ||
+ | Der Divisionsrest lässt sich mit dem Modulo-Operator '' | ||
+ | wenn beide Operanden ganzzahlig sind: | ||
+ | <code cpp> | ||
+ | | ||
+ | </ | ||
+ | Die Operatoren '' | ||
+ | * [[# | ||
+ | * zweistellig für Summen- und Differenzen von Zahlen und | ||
+ | * zur Adressrechnung in der Zeigerarithmetik. | ||
+ | <code cpp> | ||
+ | int feld[10]; | ||
+ | int* p = feld+5; | ||
+ | std::cout << p-feld << ' | ||
+ | </ | ||
+ | Inkrement '' | ||
+ | senken einen Variablenwert (Zahl oder Zeiger) um eins. | ||
+ | In zusammengesetzten Ausdrücken ist die Stellung der Operatoren | ||
+ | '' | ||
+ | |||
+ | | Postfix | ||
+ | | Präfix | ||
+ | |||
+ | ==== Bitweise Operatoren ==== | ||
+ | Bitoperationen erfordern ganzzahlige Typen | ||
+ | ('' | ||
+ | Zur Illustration werden 8 bit dargestellt | ||
+ | mit dem höchstwertigen Bit (Wert 128) auf der linken Seite. | ||
+ | |||
+ | Das Bit-Komplement (Einer-Komplement, | ||
+ | <code cpp> | ||
+ | 10001011 | ||
+ | 01110100 | ||
+ | </ | ||
+ | Schiebeoperationen verrücken die Bits vom Wert des linken Operanden | ||
+ | um die rechts angegebene Anzahl von Stellen in der angegebenen Pfeilrichtung. | ||
+ | In Schieberichtung fallen Bits heraus, auf der anderen Seite werden Nullen aufgefüllt. | ||
+ | Achtung! Bei vorzeichenbehafteten Typen ist das Rechtsschieben maschinenabhängig. | ||
+ | Einige Maschinen füllen Einsen auf, wenn das Vorzeichenbit gesetzt ist. | ||
+ | <code cpp> | ||
+ | 10001011 | ||
+ | 01011000 | ||
+ | 00100010 | ||
+ | </ | ||
+ | Bitweises UND ('' | ||
+ | die in beiden Operanden auf 1 stehen: | ||
+ | <code cpp> | ||
+ | 00001111 | ||
+ | 10101010 | ||
+ | 00001010 | ||
+ | </ | ||
+ | Bitweises ausschließendes ODER (Exklusiv-ODER, | ||
+ | deren Wert sich in beiden Operanden unterscheidet: | ||
+ | <code cpp> | ||
+ | 00001111 | ||
+ | 10101010 | ||
+ | 10100101 | ||
+ | </ | ||
+ | Bitweises ODER ('' | ||
+ | die in mindestens einem Operanden auf 1 stehen: | ||
+ | <code cpp> | ||
+ | 00001111 | ||
+ | 10101010 | ||
+ | 10101111 | ||
+ | </ | ||
+ | |||
+ | ==== Vergleiche ==== | ||
+ | Vergleiche liefern einen Wahrheitswert. | ||
+ | Die Ordnungsrelationen '' | ||
+ | Der Test auf Gleichheit muss mit zwei Gleichheitszeichen '' | ||
+ | weil das einzelne '' | ||
+ | auslöst. | ||
+ | Ungleichheit '' | ||
+ | |||
+ | ==== Logische Operatoren ==== | ||
+ | Wahrheitswerte ([[.: | ||
+ | und Ausdrücke lassen sich logisch verknüpfen | ||
+ | und liefern wieder einen Wahrheitswert. | ||
+ | Ausdrücke ungleich Null gelten als wahr (), nur 0 als falsch (). | ||
+ | Weitere logische Verknüpfungen lassen sich durch Kombination bilden | ||
+ | ([[.: | ||
+ | |||
+ | | | ||
+ | | '' | ||
+ | | 0 | 0 | 1 | 0 | 0 || 0 | 1 | 1| | ||
+ | | 0 | 1 | 0 | 0 | 1 || 1 | 0 | 1| | ||
+ | | 1 | 0 | | ||
+ | | 1 | 1 | | ||
+ | |||
+ | Logische Ausdrücke werden garantiert von links nach rechts ausgewertet, | ||
+ | jedoch nur soweit, bis das Ergebnis feststeht (Kurzschlussverfahren, | ||
+ | <code cpp> | ||
+ | if (n && z/n == 0) // bei Nenner 0 wird Division nicht ausgeführt | ||
+ | { | ||
+ | std::cout << " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Entscheidungsoperator ==== | ||
+ | Der bedingte Ausdruck '' | ||
+ | Ist der erste Teilausdruck wahr, wird der folgende Dann-Zweig ausgewertet, | ||
+ | andernfalls der Wert des Sonst-Zweiges berechnet. | ||
+ | Der Dann-Ausdruck und der Sonst-Ausdruck müssen typgleich sein. | ||
+ | Das Ergebnis kann (sollte) weiterverwendet werden: | ||
+ | <code cpp> | ||
+ | x = a < b ? a : b; // Minimum von a und b | ||
+ | </ | ||
+ | |||
+ | ==== Zuweisung | ||
+ | Zuweisungen ändern Variablenwerte. | ||
+ | Die linke Seite der Zuweisung (das Ziel der Zuweisung) muss nicht unbedingt eine Variable sein. | ||
+ | Es kann ein komplizierterer Ausdruck sein, | ||
+ | der einen veränderbaren Speicherplatz (lvalue) anspricht. | ||
+ | Die Zuweisung erfolgt von rechts nach links. | ||
+ | <code cpp> | ||
+ | punkte[mannschaft] = 0; | ||
+ | x = y = z = 1; | ||
+ | </ | ||
+ | In Zuweisungsketten haben am Ende haben alle links stehenden Variablen den rechten Wert angenommen. | ||
+ | Das ist möglich, weil eine Zuweisung einen Wert erhält, nämlich den neuen Wert der linken Variable. | ||
+ | Zuweisungen können Teil eines Ausdrucks sein. | ||
+ | <code cpp> | ||
+ | while ((c = std:: | ||
+ | { | ||
+ | } | ||
+ | </ | ||
+ | Statt '' | ||
+ | wenn '' | ||
+ | oder Bit-Operator ('' | ||
+ | <code cpp> | ||
+ | x += 10; // x wird um 10 erhöht, | ||
+ | x -= 5; // x wird um 5 vermindert, | ||
+ | x *= 2; // x wird verdoppelt, | ||
+ | x /= y+2; // x wird geteilt durch y+2, usw. | ||
+ | </ | ||
+ | Die Kurzschrift (Verbundzuweisung) kommt der natürlichen Sprechweise näher als | ||
+ | <code cpp> | ||
+ | x = x+10; // Ermittle die Summe von x und 10 und weise diese x zu !:-) | ||
+ | </ | ||
+ | |||
+ | ==== Listenoperator ==== | ||
+ | Das Komma steht zwischen Parametern / Argumenten von Funktionen, | ||
+ | auch zwischen den Werten einer Aufzählungs- oder Initialisiererliste. | ||
+ | Hinter einem Typ können mehrere Bezeichner vereinbart werden, durch Komma getrennt. | ||
+ | (Aber: Jedem Funktionsparameter muss sein eigener Typ vorangestellt sein.) | ||
+ | <code cpp> | ||
+ | int i = 1, j = 2; | ||
+ | int folge[] = { 1, 2, 3 }; | ||
+ | double winkel = atan2(y, x); | ||
+ | </ | ||
+ | In Zählschleifen mit mehreren Steuervariablen kann das Komma auftreten: | ||
+ | <code cpp> | ||
+ | for (i = 0, j = strlen(s)-1; | ||
+ | { | ||
+ | swap(s[i], s[j]); | ||
+ | } | ||
+ | </ | ||
+ | Ausdrücke, durch Komma getrennt, werden streng von links nach rechts ausgewertet. | ||
+ | Ergebnistyp und Ergebniswert sind die des rechtesten Operanden. | ||
+ | Alle vorhergehenden Ergebnisse werden bis auf Seiteneffekte verworfen. | ||
+ | Aber: In welcher Reihenfolge die Argumentwerte vor einem Funktionsaufruf | ||
+ | berechnet und abgelegt werden, ist nicht definiert, sprich: compilerabhängig. | ||
+ | |||
+ | ===== Operatoren überladen ===== | ||
+ | Für die eingebauten Typen ist die [[# | ||
+ | der Operatoren festgelegt. | ||
+ | Im Zusammenhang mit neuen Typen (Aufzählungen, | ||
+ | kann für Operatoren eine neue Bedeutung eingeführt (überladen) werden. | ||
+ | Als Einschränkungen gelten: | ||
+ | * Es können keine neuen Operatoren " | ||
+ | * Rangfolge und Parameteranzahl der Operatoren sind nicht änderbar. | ||
+ | * Die Operatoren '':: | ||
+ | * Überladene Operatoren sollten ihrer gewohnten Bedeutung nahekommen (Etikette: keine Überraschungen), | ||
+ | * Der Zeigeroperator '' | ||
+ | * Vergleiche sollten Wahrheitswerte liefern. | ||
+ | |||
+ | Überladene Operatoren werden als Funktionen mit besonderen Namen definiert. | ||
+ | Ihr Name beginnt mit dem Schlüsselwort [[.: | ||
+ | gefolgt von dem Operator-Symbol. | ||
+ | Operatoren können als [[# | ||
+ | oder als [[# | ||
+ | (s. [[.: | ||
+ | |||
+ | Besondere Regeln gilt es zu beachten bei | ||
+ | [[#Ein- und Ausgabeoperatoren]], | ||
+ | [[# | ||
+ | [[# | ||
+ | [[# | ||
+ | [[# | ||
+ | [[# | ||
+ | |||
+ | ==== Operatormethoden ==== | ||
+ | <code cpp> | ||
+ | u += v; // nutzt Methode | ||
+ | </ | ||
+ | Operatormethoden erhalten den ersten Operanden implizit (*this). | ||
+ | Bei zweistelligen Operanden muss nur das rechte Argument (" | ||
+ | als Parameter übergeben werden. | ||
+ | <code cpp> | ||
+ | struct Vec | ||
+ | { | ||
+ | Vec& Vec:: | ||
+ | // ... | ||
+ | }; | ||
+ | </ | ||
+ | Operatoren, die Zugriff auf (private) Daten eines Linkswertes (lvalue) benötigen, | ||
+ | z.B. '' | ||
+ | |||
+ | ==== Operatorfunktionen ==== | ||
+ | <code cpp> | ||
+ | w = u + v; // nutzt Funktion w = operator+(u, | ||
+ | </ | ||
+ | Operatorfunktionen werden außerhalb von Klassen (global) vereinbart. | ||
+ | Benötigt eine Operatorfunktion Zugriff auf private Klassenbereiche, | ||
+ | muss die Klasse sie zur Freundin erklären | ||
+ | (Schlüsselwort [[.: | ||
+ | In diesem Beispiel ist das unnötig, da ein zugehöriger Verbundoperator exisiert: | ||
+ | <code cpp> | ||
+ | Vec operator+(Vec const& u, Vec const& v) | ||
+ | { // ausführlich: | ||
+ | return Vec(u) += v; // sum += v; | ||
+ | } // return sum; | ||
+ | </ | ||
+ | Die paarweise Bereitstellung von Operatorfunktion '' | ||
+ | führt zu effizientem Code und | ||
+ | gehört zur Etikette (Prinzip der minimierten Überraschung). | ||
+ | Interessanterweise basiert die Operatorfunktion auf dem Verbundoperator und nicht umgekehrt! | ||
+ | |||
+ | Zweistellige Operatorfunktionen arbeiten mit gleichberechtigten linken und rechten Operanden. | ||
+ | Damit sind implizite Konversionen des linken Operanden möglich: | ||
+ | <code cpp> | ||
+ | std::string s = " | ||
+ | std::string s2 = " | ||
+ | </ | ||
+ | |||
+ | ==== Ein- und Ausgabeoperatoren ==== | ||
+ | C++ nutzt die Schiebeoperatoren '' | ||
+ | für die Datenströme '' | ||
+ | Für nutzerdefinierte Typen müssen diese als [[# | ||
+ | mit dem Datenstrom als linksseitigem Argument | ||
+ | überladen werden und den Strom nach der Operation zurückliefern, | ||
+ | damit die Verkettung möglich ist. | ||
+ | |||
+ | <code cpp> | ||
+ | std:: | ||
+ | { | ||
+ | return os << v.x << ' ' << v.y << ' ' << v.z; | ||
+ | } | ||
+ | |||
+ | std:: | ||
+ | { | ||
+ | // ... sinngemäß | ||
+ | return is; | ||
+ | } | ||
+ | </ | ||
+ | Der Eingabeoperator muss das Objekt als Referenz übernehmen (Rückgabe!). | ||
+ | Er sollte dessen Werte erst ändern, | ||
+ | wenn alle notwendigen Daten erfolgreich gelesen wurden (Etikette), | ||
+ | damit Objekte nicht nicht in einen ungültigen Zustand geraten. | ||
+ | |||
+ | ==== Zuweisungsoperator ==== | ||
+ | Wenn nicht anders definiert, | ||
+ | wird jeder zusammengesetzte Typ als Byte-Block kopiert (sog. flache Kopie). | ||
+ | Zuweisungsoperatoren sollten dann definiert werden, | ||
+ | wenn auch ein [[.: | ||
+ | erforderlich ist. | ||
+ | Zumeist verwaltet eine Klasse dann dynamischen Speicher oder andere Ressourcen | ||
+ | ([[.: | ||
+ | Zuweisungsoperatoren werden nicht vererbt. | ||
+ | |||
+ | ==== Inkrement und Dekrement ==== | ||
+ | Erhöhen und Absenken können als vorangestellte (Präfix-) | ||
+ | und nachgestellte (Postfix-) Operatoren definiert werden: | ||
+ | |||
+ | <code cpp> | ||
+ | class Date | ||
+ | { | ||
+ | public: | ||
+ | Date& operator++(); | ||
+ | Date operator++(int); | ||
+ | |||
+ | // ... | ||
+ | }; | ||
+ | </ | ||
+ | Durch ein " | ||
+ | als Postfixvariante markiert. | ||
+ | Üblicherweise sollte diese den alten Wert als Kopie (rvalue) liefern. | ||
+ | |||
+ | ==== Feldindex ==== | ||
+ | <code cpp> | ||
+ | Element& | ||
+ | </ | ||
+ | Eckige Klammern machen eine Klasse konzeptionell zu etwas Feldähnlichem | ||
+ | ([[.: | ||
+ | Die Feldindex-Operatormethode kann nur einen Parameter aufnehmen. | ||
+ | Allerdings muss der Index keine Ganzzahl sein. | ||
+ | Auch sogenannte " | ||
+ | <code cpp> | ||
+ | std:: | ||
+ | telefonbuch[" | ||
+ | std::cout << telefonbuch[" | ||
+ | </ | ||
+ | |||
+ | ==== Funktionsklammern ==== | ||
+ | <code cpp> | ||
+ | Ergebnistyp Klasse:: | ||
+ | </ | ||
+ | Die Funktionsklammer kann beliebig viele Parameter aufnehmen | ||
+ | und lässt Objekte wie Funktionen agieren | ||
+ | ([[.: | ||
+ | Im mathematischen Sinne ist das Funktionsobjekt | ||
+ | ein Operator, der auf die Argumente angewendet wird. | ||
+ | |||
+ | Funktionsobjekte (Funktoren) können sich Einstellungen (Parameter) merken | ||
+ | und können ihren inneren Zustand ändern. | ||
+ | Dadurch wird die Anzahl der Argumente beim Aufruf verringert. | ||
+ | Funktoren kommen u.a. in den [[.: | ||
+ | |||
+ | ==== Typumwandlung ==== | ||
+ | Umwandlungsmethoden erlauben, Objekte in einen anderen | ||
+ | zuvor definierten Typ zu konvertieren. | ||
+ | Der Ergebnistyp steht hinter dem Schlüsselwort '' | ||
+ | Der Typkonverter '' | ||
+ | ist das Gegenstück (die Umkehrung) zu einem Konstruktor '' | ||
+ | <code cpp> | ||
+ | struct Bruch | ||
+ | { | ||
+ | long z, n; | ||
+ | |||
+ | operator double() const // umwandeln in Dezimalbruch | ||
+ | { | ||
+ | return double(z)/ | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | Bruch b = { 1, 2 }; | ||
+ | double x = b; // 0.5, implizite Typumwandlung | ||
+ | double y = double(b); | ||
+ | </ | ||
+ | Vorsicht! | ||
+ | Durch ein Zuviel schlägt die beabsichtigte Vereinfachung ins Gegenteil um. | ||
+ | Durch Konstruktoren und Typkonverter sollten keine Zyklen | ||
+ | im Typ-Umwandlungs-Graphen entstehen. | ||
+ | Auch mehrere Typumwandlungen in ähnliche Typen schaffen Probleme. | ||
+ | Der Compiler versucht bei Nichtübereinstimmung | ||
+ | automatisch (implizit) Typen zu konvertieren, | ||
+ | indem er Konstruktoren und Typkonverter untersucht. | ||
+ | Findet der Compiler Mehrdeutigkeiten, | ||
+ | muss der Anwender durch ausdrückliche (explizite) Typkonversion nachhelfen. | ||
+ | |||
+ | ==== Benutzerdefinierte Konstanten ==== | ||
+ | Im C++-Standard 2011 als " | ||
+ | deren Ergebnis einen beliebigen, vom Nutzer definierten Typ haben kann. | ||
+ | Auf diese Weise werden einfach lesbare Anfangswerte z.B. für Maßeinheiten möglich: | ||
+ | <code cpp> | ||
+ | struct Length { double value; }; | ||
+ | |||
+ | Length operator "" | ||
+ | { | ||
+ | return { double(x) / 100 }; | ||
+ | } | ||
+ | |||
+ | Length length = 1.0_cm; | ||
+ | </ | ||
+ | Als Argumente sind nur die Typen '' | ||
+ | Bei Zeichenkettenliteralen gibt der zweite Parameter die Anzahl der Zeichen ohne Ende-Null an. | ||
+ | Literal-Anhängsel ohne Unterstrich sind für künftige Standardisierungen reserviert. | ||
+ | |||
+ | Vorsicht: Wie bei jedem neuen Merkmal besteht die Gefahr des übermäßigen Gebrauchs. |
kennen/operator.txt · Zuletzt geändert: 2020-07-27 09:55 von 127.0.0.1