static_cast
conversion
Konvertiert zwischen Typen unter Verwendung einer Kombination aus impliziten und benutzerdefinierten Konvertierungen.
Inhaltsverzeichnis |
Syntax
static_cast<
target-type
>(
expression
)
|
|||||||||
Gibt einen Wert vom Typ target-type zurück.
Erklärung
Nur die folgenden Konvertierungen können mit static_cast durchgeführt werden, außer wenn solche Konvertierungen Constness entfernen würden (oder Volatilität).
Base
" ist und
target-type
"Referenz auf
cv2
Derived
" ist, referenziert das Ergebnis das Objekt vom Typ
Derived
, das
expression
umschließt, wenn alle folgenden Bedingungen erfüllt sind:
-
Derivedist ein vollständiger Klassentyp. -
Baseist eine Basisklasse vonDerived. - cv1 ist keine stärkere CV-Qualifikation als cv2 .
-
Baseist eine virtuelle Basisklasse vonDerived. -
Baseist eine Basisklasse einer virtuellen Basisklasse vonDerived. -
Keine gültige
Standardkonvertierung
von "Zeiger auf
Derived" zu "Zeiger aufBase" existiert.
Derived
ist, ist das Verhalten undefiniert.
struct B {}; struct D : B { B b; }; D d; B& br1 = d; B& br2 = d.b; static_cast<D&>(br1); // OK, L-Wert bezeichnet das ursprüngliche "d"-Objekt static_cast<D&>(br2); // UB: Das "b"-Subobjekt ist kein Basisklassen-Subobjekt
|
2)
Wenn
target-type
"Rvalue-Referenz auf
Derived
" ist und
expression
ein Xvalue vom Typ "(möglicherweise cv-qualifiziert)
Base
" ist, sodass
Base
eine Basisklasse von
Derived
ist, dann sind das Ergebnis und die Einschränkungen einer solchen Konvertierung dieselben wie bei der "
Base
-Lvalue-zu-
Derived
-Referenz"-Konvertierung.
3)
Wenn
target-type
ein Rvalue-Referenztyp ist und der referenzierte Typ
referenzkompatibel
mit dem Typ von
expression
ist, konvertiert
static_cast
den Wert von
Glvalue, Klassen-Prvalue oder Array-Prvalue
(bis C++17)
jedem Lvalue
(seit C++17)
expression
zu einem Xvalue, der sich auf dasselbe Objekt wie der Ausdruck oder auf dessen Basisklassen-Subobjekt bezieht (abhängig von
target-type
).
[1]
Wenn
target-type
eine unzugängliche oder mehrdeutige Basis des Typs von
expression
ist, ist das Programm fehlerhaft.
Wenn
expression
ein
Bitfeld
-Lvalue ist, wird es zunächst in einen Prvalue des zugrundeliegenden Typs konvertiert.
|
(seit C++11) |
|
die Deklaration target-type temp ( expression ) ; für eine erfundene temporäre Variable temp wohlgeformt ist. Der Effekt einer solchen expliziten Konvertierung ist derselbe wie das Ausführen der Deklaration und Initialisierung und dann die Verwendung von temp als Ergebnis der Konvertierung. Die expression wird als ein Lvalue (bis C++11) ein Glvalue (seit C++11) verwendet genau dann, wenn die Initialisierung sie als ein Lvalue (bis C++11) ein Glvalue (seit C++11) verwendet. |
(bis C++17) | ||
|
eine der folgenden Bedingungen erfüllt ist:
Die explizite Konvertierung ist wie folgt definiert:
|
(seit C++17) |
- Lvalue-zu-Rvalue-Konvertierung
- Array-zu-Zeiger-Konvertierung
- Funktion-zu-Zeiger-Konvertierung
- Nullzeiger-Konvertierung
- Null-Mitgliedszeiger-Konvertierung
- Boolesche Konvertierung
| (seit C++17) |
|
a)
Ein Wert eines
scoped enumeration
-Typs kann in einen Integer- oder Gleitkommatyp konvertiert werden.
|
(seit C++11) |
- Wenn target-type einen festen zugrundeliegenden Typ hat, wird expression zunächst durch integral promotion oder integral conversion bei Bedarf in diesen Typ konvertiert und anschließend in target-type .
- Wenn target-type keinen festen zugrundeliegenden Typ hat, bleibt der Wert von expression unverändert, wenn der ursprüngliche Wert within the range of the enumeration values ist, andernfalls ist das Verhalten undefiniert.
|
d)
Ein Prvalue eines Gleitkommatyps kann explizit in jeden anderen Gleitkommatyp konvertiert werden.
|
(since C++23) |
Base
" kann explizit in den Typ "Zeiger auf
cv2
Derived
" konvertiert werden, wenn alle folgenden Bedingungen erfüllt sind:
-
Derivedist ein vollständiger Klassentyp. -
Baseist eine Basisklasse vonDerived. - cv1 ist keine stärkere CV-Qualifizierung als cv2 .
Derived
, das das Objekt vom Typ
Base
umschließt, auf das
expression
zeigt.
-
Baseist eine virtuelle Basisklasse vonDerived. -
Baseist eine Basisklasse einer virtuellen Basisklasse vonDerived. -
Keine gültige Standardkonvertierung von "Zeiger auf
Derived" zu "Zeiger aufBase" existiert.
Derived
zeigt, ist das Verhalten undefiniert.
Derived
vom Typ
cv1
T
" kann explizit in den Typ "Zeiger auf Mitglied von
Base
vom Typ
cv2
T
" konvertiert werden, wenn alle folgenden Bedingungen erfüllt sind:
-
Derivedist ein vollständiger Klassentyp. -
Baseist eine Basisklasse vonDerived. - cv1 ist keine stärkere CV-Qualifizierung als cv2 .
Base
.
Base
vom Typ
T
" zu "Zeiger auf Member von
Derived
vom Typ
T
" existiert, ist das Programm fehlerhaft.
Base
ist, ist das Verhalten undefiniert.
T
" konvertiert werden, wenn
T
ein Objekttyp ist und
cv1
keine stärkere CV-Qualifizierung als
cv2
darstellt.
|
(bis C++17) |
|
(seit C++17) |
Wie bei allen Umwandlungsausdrücken ist das Ergebnis:
- ein lvalue, wenn target-type ein lvalue reference type ist oder ein rvalue reference to function type (seit C++11) ;
|
(since C++11) |
- ein prvalue andernfalls.
- ↑ Diese Art von static_cast wird verwendet, um Move-Semantik in std::move zu implementieren.
- ↑ Falls IEEE-Arithmetik unterstützt wird, ist das Standardrundungsverfahren "Round to Nearest".
Zeiger-interkonvertierbare Objekte
Zwei Objekte a und b sind zeigerinterkonvertierbar wenn:
- sie dasselbe Objekt sind, oder
- eines ein Union-Objekt und das andere ein nicht-statisches Datenelement dieses Objekts ist, oder
- eines ein Standard-Layout Klassenobjekt und das andere das erste nicht-statische Datenelement dieses Objekts oder irgendein Basisklassen-Subobjekt dieses Objekts ist, oder
- ein Objekt c existiert, sodass a und c zeigerinterkonvertierbar sind, und c und b zeigerinterkonvertierbar sind.
union U { int a; double b; } u; void* x = &u; // Der Wert von x ist „Zeiger auf u“ double* y = static_cast<double*>(x); // Der Wert von y ist „Zeiger auf u.b“ char* z = static_cast<char*>(x); // Der Wert von z ist „Zeiger auf u“
Hinweise
Basis-zu-abgeleitet-Konvertierungen (
Downcasts
) mit
static_cast
führen keine Laufzeitprüfungen durch, um sicherzustellen, dass der
dynamische Typ
des gezeigten/referenzierten Objekts
Derived
ist, und können nur sicher verwendet werden, wenn diese Voraussetzung durch andere Mittel gewährleistet ist, wie beispielsweise bei der Implementierung von
statischem Polymorphismus
. Sichere Downcasts können mit
dynamic_cast
durchgeführt werden.
static_cast kann auch verwendet werden, um Funktionsüberladungen zu disambiguieren, indem eine Funktion-zu-Zeiger-Konvertierung zu einem spezifischen Typ durchgeführt wird, wie in
std::for_each(files.begin(), files.end(), static_cast<std::ostream&(*)(std::ostream&)>(std::flush));
Schlüsselwörter
Beispiel
#include <iostream> #include <vector> struct B { int m = 42; const char* hello() const { return "Hello world, this is B!\n"; } }; struct D : B { const char* hello() const { return "Hello world, this is D!\n"; } }; enum class E { ONE = 1, TWO, THREE }; enum EU { ONE = 1, TWO, THREE }; int main() { // 1. statischer Downcast D d; B& br = d; // Upcast durch implizite Konvertierung std::cout << "1) " << br.hello(); D& another_d = static_cast<D&>(br); // Downcast std::cout << "1) " << another_d.hello(); // 3. Lvalue zu Xvalue std::vector<int> v0{1, 2, 3}; std::vector<int> v2 = static_cast<std::vector<int>&&>(v0); std::cout << "3) nach Move, v0.size() = " << v0.size() << '\n'; // 4. Ausdruck mit verworfenem Wert static_cast<void>(v2.size()); // 5. Initialisierungskonvertierung int n = static_cast<int>(3.14); std::cout << "5) n = " << n << '\n'; std::vector<int> v = static_cast<std::vector<int>>(10); std::cout << "5) v.size() = " << v.size() << '\n'; // 6. Umkehrung der impliziten Konvertierung void* nv = &n; int* ni = static_cast<int*>(nv); std::cout << "6) *ni = " << *ni << '\n'; // 7a. Scoped Enum zu int E e = E::TWO; int two = static_cast<int>(e); std::cout << "7a) " << two << '\n'; // 7b. int zu Enum, Enum zu anderem Enum E e2 = static_cast<E>(two); [[maybe_unused]] EU eu = static_cast<EU>(e2); // 7f. Zeiger auf Member-Upcast int D::*pm = &D::m; std::cout << "7f) " << br.*static_cast<int B::*>(pm) << '\n'; // 7g. void* zu beliebigem Objektzeiger void* voidp = &e; [[maybe_unused]] std::vector<int>* p = static_cast<std::vector<int>*>(voidp); }
Ausgabe:
1) Hallo Welt, dies ist B! 1) Hallo Welt, dies ist D! 3) nach Verschiebung, v0.size() = 0 5) n = 3 5) v.size() = 10 6) *ni = 3 7a) 2 7f) 42
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 137 | C++98 |
die Konstanz und Volatilität von
Zeigern auf void konnten weggecastet werden |
CV-Qualifizierungen können in
solchen Fällen nicht weggecastet werden |
| CWG 427 | C++98 | Downcast könnte mit Direktinitialisierung mehrdeutig sein | wählt in diesem Fall Downcast aus |
| CWG 439 | C++98 |
beim Konvertieren eines "Zeigers auf Objekt" zu "Zeiger auf
void " und zurück zu sich selbst konnte der Wert nur erhalten bleiben, wenn der Ergebnistyp dieselbe CV-Qualifizierung hat |
CV-Qualifizierung
kann unterschiedlich sein |
| CWG 1094 | C++98 |
die Konvertierung von Gleitkommawerten
zu Aufzählungswerten war nicht spezifiziert |
spezifiziert |
| CWG 1320 | C++11 |
die Konvertierung von scoped enumeration
Werten zu bool war nicht spezifiziert |
spezifiziert |
| CWG 1412 | C++98 |
das Ergebnis der Konvertierung von
"Zeiger auf void " zu "Zeiger auf Objekt" war unklar |
klargestellt |
| CWG 1447 | C++11 |
die Konvertierung von Bitfeldern zu Rvalue-Referenzen
war nicht spezifiziert (Referenzen können nicht an Bitfelder gebunden werden) |
spezifiziert |
| CWG 1766 | C++98 |
die Konvertierung von Ganzzahl- oder Aufzählungswerten zu Aufzählungswerten
ergab ein nicht spezifiziertes Ergebnis, wenn expression außerhalb des Bereichs liegt |
das Verhalten ist
in diesem Fall undefiniert |
| CWG 1832 | C++98 |
die Konvertierung von Ganzzahl- oder Aufzählungswerten zu
Aufzählungswerten erlaubte, dass target-type unvollständig sein konnte |
nicht erlaubt |
| CWG 2224 | C++98 |
die Konvertierung von einem Member vom Basistyp zu
seinem vollständigen Objekt vom abgeleiteten Klassentyp war gültig |
das Verhalten ist
in diesem Fall undefiniert |
| CWG 2254 | C++11 |
ein Standard-Layout-Klassenobjekt ohne Datenelemente
war zeigerinterkonvertierbar mit seiner ersten Basisklasse |
es ist zeigerinterkonvertierbar
mit jeder seiner Basisklassen |
| CWG 2284 | C++11 |
ein Nicht-Standard-Layout-Union-Objekt und ein nicht-statisches Datenelement
dieses Objekts waren nicht zeigerinterkonvertierbar |
sie sind es |
| CWG 2310 | C++98 |
für Basis-zu-abgeleitet Zeigerkonvertierungen und
abgeleitet-zu-Basis Zeiger-zu-Member-Konvertierungen konnte der abgeleitete Klassentyp unvollständig sein |
muss vollständig sein |
| CWG 2338 | C++11 |
die Konvertierung zu Aufzählungstypen mit festem zugrundeliegendem Typ
führte zu undefiniertem Verhalten, wenn expression außerhalb des Bereichs liegt |
zuerst zum zugrundeliegenden Typ
konvertieren (kein undefiniertes Verhalten) |
| CWG 2499 | C++11 |
eine Standard-Layout-Klasse könnte eine nicht-zeigerinterkonvertierbare
Basisklasse haben, obwohl alle Basis-Subobjekte dieselbe Adresse haben |
hat sie nicht |
| CWG 2718 | C++98 |
für Basis-zu-abgeleitet Referenzkonvertierungen
konnte der abgeleitete Klassentyp unvollständig sein |
muss vollständig sein |
| CWG 2882 | C++98 |
es war unklar, ob
static_cast
<
void
>
(
expr
)
versucht,
eine implizite Konvertierungssequenz von expr zu void zu bilden |
kein Versuch in diesem Fall |
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 7.6.1.9 Static cast [expr.static.cast]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 7.6.1.8 Static cast [expr.static.cast]
- C++17-Standard (ISO/IEC 14882:2017):
-
- 8.2.9 Static cast [expr.static.cast]
- C++14-Standard (ISO/IEC 14882:2014):
-
- 5.2.9 Static cast [expr.static.cast]
- C++11-Standard (ISO/IEC 14882:2011):
-
- 5.2.9 Static cast [expr.static.cast]
- C++98 Standard (ISO/IEC 14882:1998):
-
- 5.2.9 Static cast [expr.static.cast]
- C++03-Standard (ISO/IEC 14882:2003):
-
- 5.2.9 Static cast [expr.static.cast]