Statischer Guss
Der statische Cast führt Konvertierungen zwischen kompatiblen Typen durch. Er ähnelt dem Cast im Stil von C, ist aber restriktiver. Der Cast im Stil von C würde es beispielsweise ermöglichen, dass ein Integer-Zeiger auf ein Char zeigt.
char c = 10; // 1 byte
int *p = (int*)&c; // 4 bytes
Da dies zu einem 4-Byte-Zeiger führt, der auf 1 Byte des zugewiesenen Speichers zeigt, führt das Schreiben auf diesen Zeiger entweder zu einem Laufzeitfehler oder überschreibt einen angrenzenden Speicher.
*p = 5; // run-time error: stack corruption
Im Gegensatz zum Cast in C erlaubt der statische Cast dem Compiler zu prüfen, ob die Datentypen von Zeiger und Pointee kompatibel sind, so dass der Programmierer diese falsche Zeigerzuweisung während der Kompilierung erkennen kann.
int *q = static_cast<int*>(&c); // compile-time error
Besetzung neu interpretieren
Um die Zeigerumwandlung zu erzwingen, so wie es der C-artige Cast im Hintergrund tut, würde stattdessen der reinterpret cast verwendet werden.
int *r = reinterpret_cast<int*>(&c); // forced conversion
Dieser Cast dient der Konvertierung zwischen bestimmten nicht verwandten Typen, z. B. von einem Zeigertyp in einen anderen inkompatiblen Zeigertyp. Es wird einfach eine binäre Kopie der Daten durchgeführt, ohne das zugrunde liegende Bitmuster zu verändern. Beachten Sie, dass das Ergebnis einer solchen Low-Level-Operation systemspezifisch und daher nicht portabel ist. Sie sollte mit Vorsicht verwendet werden, wenn sie nicht gänzlich vermieden werden kann.
Dynamische Besetzung
Dieser wird nur verwendet, um Objektzeiger und Objektreferenzen in andere Zeiger- oder Referenztypen in der Vererbungshierarchie umzuwandeln. Es ist der einzige Cast, der sicherstellt, dass das Objekt, auf das er zeigt, konvertiert werden kann, indem er zur Laufzeit überprüft, ob der Zeiger auf ein vollständiges Objekt des Zieltyps verweist. Damit diese Prüfung zur Laufzeit möglich ist, muss das Objekt polymorph sein. Das heißt, die Klasse muss mindestens eine virtuelle Funktion definieren oder erben. Der Grund dafür ist, dass der Compiler die benötigten Laufzeit-Typinformationen nur für solche Objekte erzeugt.
Dynamische Besetzungsbeispiele
Im folgenden Beispiel wird eine MyChild
Zeiger wird in eine MyBase
Zeiger mit einem dynamischen Cast. Diese abgeleitete Umwandlung in ein Basisobjekt ist erfolgreich, da das Child-Objekt ein vollständiges Base-Objekt enthält.
class MyBase
{
public:
virtual void test() {}
};
class MyChild : public MyBase {};
int main()
{
MyChild *child = new MyChild();
MyBase *base = dynamic_cast<MyBase*>(child); // ok
}
Im nächsten Beispiel wird versucht, eine MyBase
Zeiger auf eine MyChild
Zeiger. Da das Base-Objekt kein vollständiges Child-Objekt enthält, schlägt diese Zeigerumwandlung fehl. Um dies anzuzeigen, gibt der dynamische Cast einen Null-Zeiger zurück. Auf diese Weise kann zur Laufzeit überprüft werden, ob eine Konvertierung erfolgreich war oder nicht.
MyBase *base = new MyBase();
MyChild *child = dynamic_cast<MyChild*>(base);
if (child == 0)
std::cout << "Null pointer returned";
Wenn eine Referenz anstelle eines Zeigers konvertiert wird, schlägt der dynamische Cast fehl, indem ein bad_cast
Ausnahme. Diese muss mit einer try-catch
Erklärung.
#include <exception>
// …
try
{
MyChild &child = dynamic_cast<MyChild&>(*base);
}
catch(std::bad_cast &e)
{
std::cout << e.what(); // bad dynamic_cast
}
Dynamischer oder statischer Wurf
Der Vorteil eines dynamischen Casts besteht darin, dass der Programmierer während der Laufzeit prüfen kann, ob eine Konvertierung erfolgreich war oder nicht. Der Nachteil ist, dass diese Prüfung mit einem Leistungs-Overhead verbunden ist. Aus diesem Grund wäre im ersten Beispiel ein statischer Cast vorzuziehen gewesen, da eine abgeleitete Konvertierung in eine Basis nie fehlschlägt.
MyBase *base = static_cast<MyBase*>(child); // ok
Im zweiten Beispiel kann die Umwandlung jedoch entweder gelingen oder scheitern. Sie wird fehlschlagen, wenn die MyBase
Objekt enthält eine MyBase
Instanz und wird erfolgreich sein, wenn sie eine MyChild
Beispiel. In manchen Situationen kann dies bis zur Laufzeit nicht bekannt sein. In diesem Fall ist ein dynamischer Cast die bessere Wahl als ein statischer Cast.
// Succeeds for a MyChild object
MyChild *child = dynamic_cast<MyChild*>(base);
Wäre die Konvertierung von Basis zu abgeleitet mit einem statischen Cast statt einem dynamischen Cast durchgeführt worden, wäre die Konvertierung nicht fehlgeschlagen. Sie hätte einen Zeiger zurückgegeben, der auf ein unvollständiges Objekt verweist. Die Dereferenzierung eines solchen Zeigers kann zu Laufzeitfehlern führen.
// Allowed, but invalid
MyChild *child = static_cast<MyChild*>(base);
// Incomplete MyChild object dereferenced
(*child);
Konst Besetzung
Dieser wird in erster Linie verwendet, um die const
Modifikator einer Variablen.
const int myConst = 5;
int *nonConst = const_cast<int*>(&myConst); // removes const
Obwohl const
cast die Änderung des Wertes einer Konstante erlaubt, ist dies dennoch ungültiger Code, der einen Laufzeitfehler verursachen kann. Dies könnte beispielsweise der Fall sein, wenn sich die Konstante in einem Bereich mit schreibgeschütztem Speicher befindet.
*nonConst = 10; // potential run-time error
const
cast wird stattdessen hauptsächlich dann verwendet, wenn es eine Funktion gibt, die ein nicht konstantes Zeigerargument annimmt, auch wenn sie den Zeiger nicht verändert.
void print(int *p)
{
std::cout << *p;
}
Der Funktion kann dann eine konstante Variable übergeben werden, indem man eine const
Besetzung.
print(&myConst); // error: cannot convert
// const int* to int*
print(nonConst); // allowed
Quelle und weitere Erklärungen
78 Stimmen
Ich würde den Cast im alten C-Stil nicht als "regulären Cast" in C++ bezeichnen, da er alles andere als das ist. Man sollte ihn in C++ generell nicht verwenden, vor allem nicht bei Klassen, denn es ist einfach zu einfach, damit Fehler zu machen. Seine Verwendung ist ein Zeichen für einen C-Programmierer, der zu C++ gewechselt ist, aber C++ noch nicht ganz gelernt hat.
136 Stimmen
Wie kann eine Frage mit einer Antwort ein Duplikat einer Frage ohne Antwort sein? mehr noch, diese Frage wurde früher gestellt als das "Original"
7 Stimmen
@Vladp Für den Fall, dass Sie sich immer noch fragen, oder jemand anderes dies liest und sich fragt . (Außerdem war es kein Moderator, der die Seite geschlossen hat, sondern ein Benutzer mit einer dupe-hammer )
5 Stimmen
Zu Ihrer Information: Die verknüpfte Frage hat viel mehr Bewertungen und die Antworten haben auch viel mehr Bewertungen. Auch die verlinkte Frage hat einige gute nicht-theoretische Beispiele . (Außerdem wird in der verlinkten Frage nicht fälschlicherweise auf die Syntax des C-Typs als "regular cast" verwiesen).