operator overloading
Passt die C++-Operatoren für Operanden benutzerdefinierter Typen an.
Syntax
Operatorfunktionen sind Funktionen mit speziellen Funktionsnamen:
operator
op
|
(1) | ||||||||
operator
new
operator
new []
|
(2) | ||||||||
operator
delete
operator
delete []
|
(3) | ||||||||
operator
co_await
|
(4) | (seit C++20) | |||||||
| op | - | einer der folgenden Operatoren: + - * / % ^ & | ~ ! = < > + = - = * = / = % = ^ = & = | = << >> >>= <<= == ! = <= >= <=> (seit C++20) && || ++ -- , - > * - > ( ) [ ] |
Das Verhalten von Nicht-Interpunktionsoperatoren wird auf ihren jeweiligen eigenen Seiten beschrieben. Sofern nicht anders angegeben, gilt die verbleibende Beschreibung auf dieser Seite nicht für diese Funktionen.
Erklärung
Wenn ein Operator in einem Ausdruck auftritt und mindestens einer seiner Operanden einen Klassentyp oder einen Aufzählungstyp hat, dann wird Überladungsauflösung verwendet, um die benutzerdefinierte Funktion zu bestimmen, die unter allen Funktionen aufgerufen werden soll, deren Signaturen mit Folgendem übereinstimmen:
| Ausdruck | Als Member-Funktion | Als Nicht-Member-Funktion | Beispiel |
|---|---|---|---|
| @a | (a).operator@ ( ) | operator@ (a) | ! std:: cin ruft auf std:: cin . operator ! ( ) |
| a@b | (a).operator@ (b) | operator@ (a, b) | std:: cout << 42 ruft auf std:: cout . operator << ( 42 ) |
| a=b | (a).operator= (b) | kann nicht als Nicht-Member definiert werden | Gegeben std:: string s ; , s = "abc" ; ruft auf s. operator = ( "abc" ) |
| a(b...) | (a).operator()(b...) | kann nicht als Nicht-Member definiert werden | Gegeben std:: random_device r ; , auto n = r ( ) ; ruft auf r. operator ( ) ( ) |
| a[b...] | (a).operator[](b...) | kann nicht als Nicht-Member definiert werden | Gegeben std:: map < int , int > m ; , m [ 1 ] = 2 ; ruft auf m. operator [ ] ( 1 ) |
| a-> | (a).operator->( ) | kann nicht als Nicht-Member definiert werden | Gegeben std:: unique_ptr < S > p ; , p - > bar ( ) ruft auf p. operator - > ( ) |
| a@ | (a).operator@ (0) | operator@ (a, 0) | Gegeben std:: vector < int > :: iterator i ; , i ++ ruft auf i. operator ++ ( 0 ) |
|
In dieser Tabelle ist
|
|||
|
Zusätzlich berücksichtigt die Überladungsauflösung für Vergleichsoperatoren == , ! = , < , > , <= , >= , <=> auch die umgeschriebenen Kandidaten operator == oder operator <=> . |
(seit C++20) |
Überladene Operatoren (aber nicht die eingebauten Operatoren) können mit Funktionsschreibweise aufgerufen werden:
std::string str = "Hallo, "; str.operator+=("Welt"); // dasselbe wie str += "Welt"; operator<<(operator<<(std::cout, str), '\n'); // dasselbe wie std::cout << str << '\n'; // (seit C++17) außer in der Ausführungsreihenfolge
Statische überladene OperatorenÜberladene Operatoren, die Elementfunktionen sind, können als static deklariert werden. Dies ist jedoch nur für operator ( ) und operator [ ] erlaubt. Solche Operatoren können mit Funktionsnotation aufgerufen werden. Wenn diese Operatoren jedoch in Ausdrücken erscheinen, benötigen sie weiterhin ein Objekt vom Klassentyp. struct SwapThem { template<typename T> static void operator()(T& lhs, T& rhs) { std::ranges::swap(lhs, rhs); } template<typename T> static void operator[](T& lhs, T& rhs) { std::ranges::swap(lhs, rhs); } }; inline constexpr SwapThem swap_them{}; void foo() { int a = 1, b = 2; swap_them(a, b); // OK swap_them[a, b]; // OK SwapThem{}(a, b); // OK SwapThem{}[a, b]; // OK SwapThem::operator()(a, b); // OK SwapThem::operator[](a, b); // OK SwapThem(a, b); // error, invalid construction SwapThem[a, b]; // error } |
(seit C++23) |
Einschränkungen
- Eine Operatorfunktion muss mindestens einen Funktionsparameter oder impliziten Objektparameter haben, dessen Typ eine Klasse, eine Referenz auf eine Klasse, eine Enumeration oder eine Referenz auf eine Enumeration ist.
-
Die Operatoren
::(Bereichsauflösung),.(Memberzugriff),.*(Memberzugriff über Zeiger auf Member) und?:(ternärer Bedingungsoperator) können nicht überladen werden. -
Neue Operatoren wie
**,<>oder&|können nicht erstellt werden. - Es ist nicht möglich, die Priorität, Gruppierung oder Anzahl der Operanden von Operatoren zu ändern.
-
Die Überladung des Operators
->muss entweder einen Rohzeiger zurückgeben oder ein Objekt (per Referenz oder per Wert) zurückgeben, für das der Operator->seinerseits überladen ist. -
Die Überladungen der Operatoren
&&und||verlieren die Kurzschlussauswertung.
|
(bis C++17) |
Kanonische Implementierungen
Neben den oben genannten Einschränkungen legt die Sprache keine weiteren Beschränkungen fest, was die überladenen Operatoren tun oder welchen Rückgabetyp sie haben (er nimmt nicht an der Überladungsauflösung teil), aber im Allgemeinen wird erwartet, dass überladene Operatoren sich möglichst ähnlich wie die eingebauten Operatoren verhalten: operator + wird erwartet zu addieren, anstatt seine Argumente zu multiplizieren, operator = wird erwartet zuzuweisen, usw. Die verwandten Operatoren werden erwartet, sich ähnlich zu verhalten ( operator + und operator + = führen die gleiche additionsähnliche Operation durch). Die Rückgabetypen werden durch die Ausdrücke begrenzt, in denen der Operator verwendet werden soll: Zum Beispiel geben Zuweisungsoperatoren per Referenz zurück, um das Schreiben von a = b = c = d zu ermöglichen, weil die eingebauten Operatoren dies erlauben.
Häufig überladene Operatoren haben folgende typische, kanonische Formen: [1]
Zuweisungsoperator
Der Zuweisungsoperator operator = besitzt spezielle Eigenschaften: siehe copy assignment und move assignment für Details.
Der kanonische Kopierzuweisungsoperator wird erwartet, sicher bei Selbstzuweisung zu sein und die linke Seite als Referenz zurückzugeben:
// Kopierzuweisung T& operator=(const T& other) { // Selbstzuweisung prüfen if (this == &other) return *this; // annehmen *this verwaltet eine wiederverwendbare Ressource, wie einen heap-allokierten Puffer mArray if (size != other.size) // Ressource in *this kann nicht wiederverwendet werden { temp = new int[other.size]; // Ressource allokieren, falls Exception, nichts tun delete[] mArray; // Ressource in *this freigeben mArray = temp; size = other.size; } std::copy(other.mArray, other.mArray + other.size, mArray); return *this; }
|
Die kanonische Move-Zuweisung wird erwartet, das verschobene Objekt in einem gültigen Zustand zu belassen (d.h. in einem Zustand mit intakten Klasseninvarianten), und entweder nichts zu tun oder zumindest das Objekt bei Selbstzuweisung in einem gültigen Zustand zu belassen, und die linke Seite als Referenz auf Nicht-Konstantes zurückzugeben, und noexcept zu sein: // move assignment T& operator=(T&& other) noexcept { // Guard self assignment if (this == &other) return *this; // delete[]/size=0 would also be ok delete[] mArray; // release resource in *this mArray = std::exchange(other.mArray, nullptr); // leave other in valid state size = std::exchange(other.size, 0); return *this; } |
(seit C++11) |
In jenen Situationen, in denen die Kopierzuweisung nicht von der Wiederverwendung von Ressourcen profitieren kann (sie verwaltet kein heap-alloziertes Array und hat kein (möglicherweise transitives) Member, das dies tut, wie etwa ein Member std::vector oder std::string ), gibt es eine beliebte praktische Abkürzung: den Copy-and-Swap-Zuweisungsoperator, der seinen Parameter als Wert übernimmt (somit sowohl als Kopier- als auch als Verschiebezuweisung funktioniert, abhängig von der Wertkategorie des Arguments), mit dem Parameter swap ausführt und den Destruktor die Bereinigung überlässt.
// Kopierzuweisung (Copy-and-Swap Idiom) T& T::operator=(T other) noexcept // ruft Kopier- oder Move-Konstruktor auf, um other zu konstruieren { std::swap(size, other.size); // tauscht Ressourcen zwischen *this und other aus std::swap(mArray, other.mArray); return *this; } // Destruktor von other wird aufgerufen, um die zuvor von *this verwalteten Ressourcen freizugeben
Dieses Formular bietet automatisch strong exception guarantee , verbietet jedoch die Wiederverwendung von Ressourcen.
Stream-Extraktion und -Einfügung
Die Überladungen von
operator>>
und
operator<<
, die ein
std::
istream
&
oder
std::
ostream
&
als linkes Argument nehmen, werden als Einfüge- und Extraktionsoperatoren bezeichnet. Da sie den benutzerdefinierten Typ als rechtes Argument nehmen (
b
in
a @ b
), müssen sie als Nicht-Member-Funktionen implementiert werden.
std::ostream& operator<<(std::ostream& os, const T& obj) { // Objekt in Stream schreiben return os; } std::istream& operator>>(std::istream& is, T& obj) { // Objekt aus Stream lesen if (/* T konnte nicht konstruiert werden */) is.setstate(std::ios::failbit); return is; }
Diese Operatoren werden manchmal als friend functions implementiert.
Funktionsaufrufoperator
Wenn eine benutzerdefinierte Klasse den Funktionsaufrufoperator operator ( ) überlädt, wird sie zu einem FunctionObject -Typ.
Ein Objekt eines solchen Typs kann in einem Funktionsaufrufausdruck verwendet werden:
// Ein Objekt dieses Typs repräsentiert eine lineare Funktion einer Variablen a * x + b. struct Linear { double a, b; double operator()(double x) const { return a * x + b; } }; int main() { Linear f{2, 1}; // Repräsentiert die Funktion 2x + 1. Linear g{-1, 0}; // Repräsentiert die Funktion -x. // f und g sind Objekte, die wie eine Funktion verwendet werden können. double f_0 = f(0); double f_1 = f(1); double g_0 = g(0); }
Viele Standardbibliothek- Algorithmen akzeptieren FunctionObject s zur Anpassung des Verhaltens. Es gibt keine besonders bemerkenswerten kanonischen Formen von operator ( ) , aber zur Veranschaulichung der Verwendung:
#include <algorithm> #include <iostream> #include <vector> struct Sum { int sum = 0; void operator()(int n) { sum += n; } }; int main() { std::vector<int> v = {1, 2, 3, 4, 5}; Sum s = std::for_each(v.begin(), v.end(), Sum()); std::cout << "The sum is " << s.sum << '\n'; }
Ausgabe:
The sum is 15
Inkrement und Dekrement
Wenn der Postfix-Inkrement- oder -Dekrement-Operator in einem Ausdruck erscheint, wird die entsprechende benutzerdefinierte Funktion ( operator ++ oder operator -- ) mit einem ganzzahligen Argument 0 aufgerufen. Typischerweise wird sie deklariert als T operator ++ ( int ) oder T operator -- ( int ) , wobei das Argument ignoriert wird. Die Postfix-Inkrement- und -Dekrement-Operatoren werden üblicherweise mithilfe der Präfix-Versionen implementiert:
struct X { // Präfix-Inkrement X& operator++() { // tatsächliche Erhöhung findet hier statt return *this; // neuen Wert als Referenz zurückgeben } // Postfix-Inkrement X operator++(int) { X old = *this; // alten Wert kopieren operator++(); // Präfix-Inkrement return old; // alten Wert zurückgeben } // Präfix-Dekrement X& operator--() { // tatsächliche Verringerung findet hier statt return *this; // neuen Wert als Referenz zurückgeben } // Postfix-Dekrement X operator--(int) { X old = *this; // alten Wert kopieren operator--(); // Präfix-Dekrement return old; // alten Wert zurückgeben } };
Obwohl die kanonischen Implementierungen der Präfix-Inkrement- und Dekrement-Operatoren per Referenz zurückgeben, ist der Rückgabetyp – wie bei jeder Operatorüberladung – benutzerdefiniert; beispielsweise geben die Überladungen dieser Operatoren für std::atomic per Wert zurück.
Binäre arithmetische Operatoren
Binäre Operatoren werden typischerweise als Nicht-Member implementiert, um Symmetrie zu wahren (wenn man beispielsweise eine komplexe Zahl und eine Ganzzahl addiert, würde nur operator + als Member-Funktion des komplexen Typs kompilieren, und nicht integer + complex ). Da es für jeden binären arithmetischen Operator einen entsprechenden zusammengesetzten Zuweisungsoperator gibt, werden kanonische Formen binärer Operatoren mittels ihrer zusammengesetzten Zuweisungen implementiert:
class X { public: X& operator+=(const X& rhs) // zusammengesetzte Zuweisung (muss kein Member sein, { // ist es aber oft, um private Member zu modifizieren) /* addition of rhs to *this takes place here */ return *this; // Ergebnis als Referenz zurückgeben } // im Klassenkörper definierte friend-Funktionen sind inline und vor nicht-ADL-Lookup verborgen friend X operator+(X lhs, // Übergabe von lhs als Wert optimiert verkettete a+b+c const X& rhs) // andernfalls können beide Parameter const-Referenzen sein { lhs += rhs; // zusammengesetzte Zuweisung wiederverwenden return lhs; // Ergebnis als Wert zurückgeben (verwendet Move-Konstruktor) } };
Vergleichsoperatoren
Standardbibliotheksalgorithmen wie std::sort und Container wie std::set erwarten standardmäßig, dass operator < für benutzerdefinierte Typen definiert ist, und erwarten, dass dieser eine strenge schwache Ordnung implementiert (und somit die Compare -Anforderungen erfüllt). Eine idiomatische Methode zur Implementierung einer strengen schwachen Ordnung für eine Struktur ist die Verwendung des lexikographischen Vergleichs, der durch std::tie bereitgestellt wird:
struct Record { std::string name; unsigned int floor; double weight; friend bool operator<(const Record& l, const Record& r) { return std::tie(l.name, l.floor, l.weight) < std::tie(r.name, r.floor, r.weight); // Reihenfolge beibehalten } };
In der Regel, sobald operator < bereitgestellt wird, werden die anderen relationalen Operatoren mittels operator < implementiert.
inline bool operator< (const X& lhs, const X& rhs) { /* tatsächlichen Vergleich durchführen */ } inline bool operator> (const X& lhs, const X& rhs) { return rhs < lhs; } inline bool operator<=(const X& lhs, const X& rhs) { return !(lhs > rhs); } inline bool operator>=(const X& lhs, const X& rhs) { return !(lhs < rhs); }
Ebenso wird der Ungleichheitsoperator typischerweise in Bezug auf operator == implementiert:
inline bool operator==(const X& lhs, const X& rhs) { /* tatsächlichen Vergleich durchführen */ } inline bool operator!=(const X& lhs, const X& rhs) { return !(lhs == rhs); }
Wenn ein Dreivergleich (wie std::memcmp oder std::string::compare ) bereitgestellt wird, können alle sechs zweistelligen Vergleichsoperatoren dadurch ausgedrückt werden:
inline bool operator==(const X& lhs, const X& rhs) { return cmp(lhs,rhs) == 0; } inline bool operator!=(const X& lhs, const X& rhs) { return cmp(lhs,rhs) != 0; } inline bool operator< (const X& lhs, const X& rhs) { return cmp(lhs,rhs) < 0; } inline bool operator> (const X& lhs, const X& rhs) { return cmp(lhs,rhs) > 0; } inline bool operator<=(const X& lhs, const X& rhs) { return cmp(lhs,rhs) <= 0; } inline bool operator>=(const X& lhs, const X& rhs) { return cmp(lhs,rhs) >= 0; }
`-Tags, der gemäß den Anweisungen nicht übersetzt werden soll. Daher bleibt der gesamte Inhalt unverändert.
Array-Subscript-Operator
Benutzerdefinierte Klassen, die array-ähnlichen Zugriff mit Lese- und Schreibmöglichkeiten bereitstellen, definieren typischerweise zwei Überladungen für operator [ ] : const- und non-const-Varianten:
struct T { value_t& operator[](std::size_t idx) { return mVector[idx]; } const value_t& operator[](std::size_t idx) const { return mVector[idx]; } };
|
Alternativ können sie als einzelne Member-Funktionsvorlage mit einem expliziten Objektparameter ausgedrückt werden: struct T { decltype(auto) operator[](this auto& self, std::size_t idx) { return self.mVector[idx]; } }; |
(seit C++23) |
Wenn der Werttyp bekanntermaßen ein Skalartyp ist, sollte die const-Variante als Wert zurückgeben.
Wenn direkter Zugriff auf die Elemente des Containers nicht erwünscht oder nicht möglich ist oder zwischen lvalue c [ i ] = v ; und rvalue v = c [ i ] ; Verwendung unterschieden werden muss, operator [ ] kann einen Proxy zurückgeben. Siehe beispielsweise std::bitset::operator[] .
|
operator [ ] kann nur einen Index akzeptieren. Um mehrdimensionale Array-Zugriffssemantik bereitzustellen, z.B. um einen 3D-Array-Zugriff zu implementieren a [ i ] [ j ] [ k ] = x ; , muss operator [ ] eine Referenz auf eine 2D-Ebene zurückgeben, die ihren eigenen operator [ ] haben muss, der eine Referenz auf eine 1D-Zeile zurückgibt, die wiederum operator [ ] haben muss, der eine Referenz auf das Element zurückgibt. Um diese Komplexität zu vermeiden, überladen einige Bibliotheken stattdessen operator ( ) , sodass 3D-Zugriffsausdrücke die Fortran-ähnliche Syntax a ( i, j, k ) = x ; haben. |
(bis C++23) |
|
operator [ ] kann beliebig viele Indizes akzeptieren. Beispielsweise kann ein operator [ ] einer 3D-Array-Klasse, deklariert als T & operator [ ] ( std:: size_t x, std:: size_t y, std:: size_t z ) ; , direkt auf die Elemente zugreifen.
Führe diesen Code aus
#include <array> #include <cassert> #include <iostream> template<typename T, std::size_t Z, std::size_t Y, std::size_t X> struct Array3d { std::array<T, X * Y * Z> m{}; constexpr T& operator[](std::size_t z, std::size_t y, std::size_t x) // C++23 { assert(x < X and y < Y and z < Z); return m[z * Y * X + y * X + x]; } }; int main() { Array3d<int, 4, 3, 2> v; v[3, 2, 1] = 42; std::cout << "v[3, 2, 1] = " << v[3, 2, 1] << '\n'; } Ausgabe: v[3, 2, 1] = 42 |
(seit C++23) |
Bitweise arithmetische Operatoren
Benutzerdefinierte Klassen und Enumerationen, die die Anforderungen von BitmaskType implementieren, müssen die bitweisen arithmetischen Operatoren operator & , operator | , operator ^ , operator~ , operator & = , operator | = , und operator ^ = überladen, und können optional die Schiebeoperatoren operator << operator >> , operator >>= , und operator <<= überladen. Die kanonischen Implementierungen folgen üblicherweise dem oben beschriebenen Muster für binäre arithmetische Operatoren.
Boolescher Negationsoperator
|
Der Operator operator ! wird häufig von benutzerdefinierten Klassen überladen, die in booleschen Kontexten verwendet werden sollen. Solche Klassen stellen auch eine benutzerdefinierte Konvertierungsfunktion zum booleschen Typ bereit (siehe std::basic_ios für das Standardbibliotheksbeispiel), und das erwartete Verhalten von operator ! ist, den umgekehrten Wert von operator bool zurückzugeben. |
(bis C++11) |
|
Da der eingebaute Operator ! eine kontextuelle Konvertierung zu bool durchführt, können benutzerdefinierte Klassen, die in booleschen Kontexten verwendet werden sollen, nur operator bool bereitstellen und müssen operator ! nicht überladen. |
(seit C++11) |
Selten überladene Operatoren
Die folgenden Operatoren werden selten überladen:
-
Der Address-of-Operator,
operator
&
. Wenn der unäre & auf einen L-Wert eines unvollständigen Typs angewendet wird und der vollständige Typ einen überladenen
operator
&
deklariert, ist es unspezifiziert, ob der Operator die eingebaute Bedeutung hat oder die Operatorfunktion aufgerufen wird. Da dieser Operator überladen werden kann, verwenden generische Bibliotheken
std::addressof
, um Adressen von Objekten benutzerdefinierter Typen zu erhalten. Das bekannteste Beispiel eines kanonisch überladenen
operator
&
ist die Microsoft-Klasse
CComPtrBase. Ein Beispiel für die Verwendung dieses Operators in EDSL findet sich in boost.spirit . - Die booleschen Logikoperatoren, operator && und operator || . Im Gegensatz zu den eingebauten Versionen können die Überladungen keine Kurzschlussauswertung implementieren. Anders als bei den eingebauten Versionen sequenzieren sie ihren linken Operanden nicht vor dem rechten. (bis C++17) In der Standardbibliothek sind diese Operatoren nur für std::valarray überladen.
- Der Komma-Operator, operator, . Im Gegensatz zur eingebauten Version sequenzieren die Überladungen ihren linken Operanden nicht vor dem rechten. (bis C++17) Da dieser Operator überladen werden kann, verwenden generische Bibliotheken Ausdrücke wie a, void ( ) , b anstelle von a, b , um die Ausführung von Ausdrücken benutzerdefinierter Typen zu sequenzieren. Die Boost-Bibliothek verwendet operator, in boost.assign , boost.spirit und anderen Bibliotheken. Die Datenbankzugriffsbibliothek SOCI überlädt ebenfalls operator, .
- Der Memberzugriff durch Pointer-to-Member operator - > * . Es gibt keine spezifischen Nachteile beim Überladen dieses Operators, aber er wird in der Praxis selten verwendet. Es wurde vorgeschlagen, dass er Teil einer Smart-Pointer-Schnittstelle sein könnte, und tatsächlich wird er in dieser Funktion von Aktoren in boost.phoenix verwendet. Er ist häufiger in EDSLs wie cpp.react zu finden.
Hinweise
| Feature-Test Makro | Wert | Std | Funktion |
|---|---|---|---|
__cpp_static_call_operator
|
202207L
|
(C++23) | static operator ( ) |
__cpp_multidimensional_subscript
|
202211L
|
(C++23) | static operator [ ] |
Schlüsselwörter
Beispiel
#include <iostream> class Fraction { // or C++17's std::gcd constexpr int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } int n, d; public: constexpr Fraction(int n, int d = 1) : n(n / gcd(n, d)), d(d / gcd(n, d)) {} constexpr int num() const { return n; } constexpr int den() const { return d; } constexpr Fraction& operator*=(const Fraction& rhs) { int new_n = n * rhs.n / gcd(n * rhs.n, d * rhs.d); d = d * rhs.d / gcd(n * rhs.n, d * rhs.d); n = new_n; return *this; } }; std::ostream& operator<<(std::ostream& out, const Fraction& f) { return out << f.num() << '/' << f.den(); } constexpr bool operator==(const Fraction& lhs, const Fraction& rhs) { return lhs.num() == rhs.num() && lhs.den() == rhs.den(); } constexpr bool operator!=(const Fraction& lhs, const Fraction& rhs) { return !(lhs == rhs); } constexpr Fraction operator*(Fraction lhs, const Fraction& rhs) { return lhs *= rhs; } int main() { constexpr Fraction f1{3, 8}, f2{1, 2}, f3{10, 2}; std::cout << f1 << " * " << f2 << " = " << f1 * f2 << '\n' << f2 << " * " << f3 << " = " << f2 * f3 << '\n' << 2 << " * " << f1 << " = " << 2 * f1 << '\n'; static_assert(f3 == f2 * 10); }
Ausgabe:
3/8 * 1/2 = 3/16 1/2 * 5/1 = 5/2 2 * 3/8 = 3/4
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 1481 | C++98 |
der nicht-Member Präfix-Inkrementoperator konnte nur einen Parameter
vom Klassentyp, Aufzählungstyp oder Referenztyp auf solche Typen haben |
keine Typanforderung |
| CWG 2931 | C++23 |
explizite Objekt-Member-Operatorfunktionen konnten nur keinen Parameter
vom Klassentyp, Aufzählungstyp oder Referenztyp auf solche Typen haben |
verboten |
Siehe auch
| Häufig verwendete Operatoren | ||||||
|---|---|---|---|---|---|---|
| Zuweisung |
Inkrement
Dekrement |
Arithmetik | Logisch | Vergleich |
Member
Zugriff |
Sonstige |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
...
]
|
Funktionsaufruf
a ( ... ) |
|
Komma
a, b |
||||||
|
Bedingungsoperator
a ? b : c |
||||||
| Spezielle Operatoren | ||||||
|
static_cast
konvertiert einen Typ in einen anderen verwandten Typ
|
||||||
Externe Links
|