Der Hauptgrund dafür ist, dass die klassischen C-Casts keinen Unterschied machen zwischen dem, was wir als static_cast<>()
, reinterpret_cast<>()
, const_cast<>()
y dynamic_cast<>()
. Diese vier Dinge sind völlig unterschiedlich.
A static_cast<>()
ist normalerweise sicher. Es gibt eine gültige Konvertierung in der Sprache oder einen geeigneten Konstruktor, der dies möglich macht. Das einzige Mal, dass es ein wenig riskant ist, ist, wenn man auf eine geerbte Klasse zurückgreift; man muss sicherstellen, dass das Objekt tatsächlich der Nachkomme ist, für den man es hält, und zwar mit Mitteln außerhalb der Sprache (z. B. einem Flag im Objekt). A dynamic_cast<>()
ist sicher, solange das Ergebnis überprüft wird (Zeiger) oder eine mögliche Ausnahme berücksichtigt wird (Verweis).
A reinterpret_cast<>()
(oder ein const_cast<>()
) ist dagegen immer gefährlich. Man sagt dem Compiler: "Vertrau mir: Ich weiß, das sieht nicht aus wie ein foo
(das sieht so aus, als ob es nicht veränderbar ist), aber es ist".
Das erste Problem ist, dass es fast unmöglich ist, zu sagen, welche in einem C-ähnlichen Cast auftreten wird, ohne sich große und verstreute Codestücke anzusehen und alle Regeln zu kennen.
Gehen wir von diesen aus:
class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;
CMyBase *pSomething; // filled somewhere
Diese beiden werden auf die gleiche Weise zusammengestellt:
CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked
pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
// Safe; as long as we checked
// but harder to read
Schauen wir uns jedoch diesen fast identischen Code an:
CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert
pOther = (CMyOtherStuff*)(pSomething); // No compiler error.
// Same as reinterpret_cast<>
// and it's wrong!!!
Wie Sie sehen können, ist es nicht einfach, zwischen den beiden Situationen zu unterscheiden, ohne viel über die beteiligten Klassen zu wissen.
Das zweite Problem ist, dass die C-Würfe zu schwer zu finden sind. In komplexen Ausdrücken kann es sehr schwierig sein, die C-ähnlichen Besetzungen zu erkennen. Es ist praktisch unmöglich, ein automatisiertes Werkzeug zu schreiben, das Casts im C-Stil aufspüren muss (z. B. ein Suchwerkzeug), ohne ein vollwertiges C++-Compiler-Frontend. Andererseits ist es einfach, nach "static_cast<" oder "reinterpret_cast<" zu suchen.
pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
// No compiler error.
// but the presence of a reinterpret_cast<> is
// like a Siren with Red Flashing Lights in your code.
// The mere typing of it should cause you to feel VERY uncomfortable.
Das bedeutet nicht nur, dass Würfe im C-Stil gefährlicher sind, sondern auch, dass es viel schwieriger ist, sie alle zu finden und sicherzustellen, dass sie korrekt sind.
46 Stimmen
Einspruch, Euer Ehren, gefragt und beantwortet .
35 Stimmen
Ich stimme nicht zu, diese andere Frage war über die Beschreibung der Unterschiede zwischen casts in C++ eingeführt. Diese Frage ist über die wirkliche Nützlichkeit von static_cast, die etwas anders ist.
2 Stimmen
Wir könnten die beiden Fragen sicherlich zusammenführen, aber was wir in diesem Thread beibehalten müssten, ist der Vorteil der Verwendung von Funktionen gegenüber dem Casting im C-Stil, der derzeit nur in einer einzeiligen Antwort im anderen Thread erwähnt wird, ohne dass darüber abgestimmt wurde.
0 Stimmen
Ich stimme hoch, weil dieser Link immer noch nützliche Informationen enthält.
7 Stimmen
In dieser Frage geht es um "eingebaute" Typen, wie int, während es in dieser Frage um Klassentypen geht. Das scheint ein so bedeutender Unterschied zu sein, dass er eine separate Erklärung verdient.
13 Stimmen
Static_cast ist eigentlich ein Operator, keine Funktion.
1 Stimmen
@ThomasMcLeod Operatoren sind eine besondere Art von Funktionen (zumindest dachte ich das)
2 Stimmen
@DarthRubik, eigentlich sind Funktionsaufrufe eine Art von Operator. de.wikipedia.org/wiki/Betreiber_in_C_und_C%2B%2B
1 Stimmen
@user153275 Nun, der Titel handelt von primitiven Typen, aber die Frage wirft sie weg. Und die Antworten auch. Ich bin nicht davon überzeugt, dass ich etwas ändern muss. Ziemlich sicher
int x = (int)myfloat;
wird gut funktionieren und das tun, was ich erwarte.