Pointer type casting
-
@Ibinda100
reinterpret_castkann man verwenden um z.B. einen Zeiger in einenuintptr_tzu konvertieren - und wieder zurück (in genau den selben Zeigertyp!).
Das ist soweit ich weiss OK und vom Standard abgedeckt.Weiters kann man
reinterpret_castverwenden um z.B. einenT*in einenchar*oderunsigned char*zu verwandeln. Um dann z.B. byteweise zu kopieren. Das ist auch OK -- vorausgesetztTist dafür geeignet (memcpy-movable bzw. memcpy-copyable). Ebenfalls OK und vom Standard abgedeckt.Code wie in dem Beispiel von SeppJ sieht man auch oft. Der verletzt aber blöderweise die "strict aliasing" Regel, ist also nicht standardkonform, und kann zu UB führen. Also dazu dass das Programm nicht das macht was man erreichen wollte. Je nach Compiler geht das oft bis immer gut (MSVC) oder auch eher nicht (GCC, Clang).
Die standardkonforme Variante davon wäre den
floatmittels eineschar*oderunsigned char*in einelongVariable zu kopieren -- oder auch einfach permemcpy(und dann ebenso wieder zurück). Dummerweise kann man sich nicht darauf verlassen dass der jeweils verwendete Compiler sowas immer perfekt wegoptimiert, und daher wird oft die "verbotene" Variante mitreinterpret_castverwendet.
-
Oder wenn nur ein Offset einer Funktion in einem Modul bekannt ist, dann kann man die Funktion mit dem hier verfügbar machen:
using func_t = int WINAPI (*)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); std::size_t start_addr = reinterpret_cast<std::size_t>(GetModuleHandle("Kernel.dll")); func_t MessageBox = reinterpret_cast<func_t>(start_addr + offset)
-
welchen Vorteil bringt mir eigentlich
Derived* ptr_derived = dynamic_cast<Derived*>(ptr_base);gegenüber
Derived* ptr_derived = (Derived) ptr_base;
-
Ibinda100 schrieb:
welchen Vorteil bringt mir eigentlich
Derived* ptr_derived = dynamic_cast<Derived*>(ptr_base);gegenüber
Derived* ptr_derived = (Derived) ptr_base;Im ersten Fall macht es genau das was dort steht oder meldet einen Fehler. Im zweiten Fall würde irgendetwas ausgeführt (vermutlich würde es sogar ohne den vergessenen * übersetzen). Welcher cast ausgeführt wird, lässt sich nur anhand der Zeilen nicht vorhersagen.
-
(1)Derived* ptr_derived = dynamic_cast<Derived*>(ptr_base);
(2)Base* ptr_base = dynamic_cast<Base*>(ptr_derived);
Macht das 2.nicht mehr Sinn ? In einer derived klasse sind doch meistens viel mehr Methoden verfügbar. ptr_derived kann aber im 1.Fall nur die base methoden aufrufen. Das Intellisense der IDE würde wahrscheinlich aber alle Methoden (Base + Derived) anzeigen oder.
-
Vielleicht stellst du deine Hausaufgaben mal komplett ein, dann können wir sie abarbeiten und dir gesammelt zur Verfügung stellen.
-
ja da hab ich schon recht.
Base_Class * ptr_b = new Base_Class; Derived_Class * ptr_c = dynamic_cast< Derived_Class *>(ptr_b);Das hier geht schief , da ptr_c auf ein unvollständiges Objekt zeigen würde.Ein derived pointer kann nie auf eine Base adresse zeigen.
-
Ibinda100 schrieb:
Das hier geht schief , da ptr_c auf ein unvollständiges Objekt zeigen würde.Ein derived pointer kann nie auf eine Base adresse zeigen.
nichts "geht schief", da
dynamic_casthier einennullptrzurückgibt. eindynamic_castüberprüft zur laufzeit, welchen typ ein objekt, auf das ein zeiger oder eine referenz verweist, tatsächlich hat, sofern das vorgesehen ist (das ist es nur, wenn das objekt eine instanz einer polymorphen klasse ist, und das ist eine klasse dann, wenn sie zumindest eine virtuelle funktion deklariert), und kann einen "downcast" dann sicher ausführen. kein anderer cast kann das. das umgekehrte beispiel löst man in der regel implizit oder mit einemstatic_cast.Base* a = new Derived; Base* b = static_cast<Base*>(new Derived); //ist äquivalent und besser als Base* b = dynamic_cast<Base*>(new Derived)solltest du als programmierer aber schon ganz sicher wissen, dass ein zeiger auf Base eigentlich auf ein Derived zeigt, dann kannst du auch in diesem fall
static_castverwenden:namespace { void dumb (Base* b) { Derived* d = static_cast<Derived*>(b); } } void foo (Derived*d) { dumb(d); }dumm, weil unnötig, nicht erweiterbar, etc.
[/cpp]
-
ok dynamic_cast ist klar. Es wird zur Laufzeit geprüft ob der cast funktioniert.
Aber welche Vorteile habe ich mit static_cast,reinterpret_cast oder const_cast gegenüber einem regulären C cast.
Der reguläre C cast vereint ja alle 3 sachen. Man kann halt das Casten noch verfeinern. Man sagt dem Compiler noch genauer was man vorhat oder ?
-
Ibinda100 schrieb:
Man sagt dem Compiler noch genauer was man vorhat oder ?
Genau. Und das hilft, um Fehler früher aufzudecken.
-
und der cast ist im Code besser zu erkennen. Eine ordentliche IDE hebt sowas per Syntaxhighlighting hervor. Man könnte sogar danach suchen wenn man denn möchte.
-
@Ibinda100
Bei vielen Sachen ist es ein Vorteil wenn man so wenig wie möglich explizit hinschreiben muss, und der Compiler macht es einfach so dass es passt/geht. Wie z.B. beiauto.
Bei Casts sehe ich das aber anders. Casts sind grundsätzlich eher mit Vorsicht zu geniessen. Man kann damit viel Unsinn bauen. Und da ist es gut wenn man das was der Compiler machen darf möglichst weit einschränken kann. Einstatic_castkann z.B. wederconstwegcasten noch zwischen Zeigern auf unverwandte Klassen konvertieren. Und das ist gut. Weil es Fehler vermeidet. Speziell in Templates, aber grundsätzlich auch in ganz normalem Code.ps: Das was Braunstein geschrieben hat ist mir persönlich auch wichtig. Also Syntax-Highlighting und Suchbarkeit.
-
hustbaer schrieb:
@Ibinda100
Bei vielen Sachen ist es ein Vorteil wenn man so wenig wie möglich explizit hinschreiben muss, und der Compiler macht es einfach so dass es passt/geht. Wie z.B. beiauto.ich bin mir sicher, dass du das auch so siehst: die logik dahinter, die casts so kompliziert zu machen ist die gleiche, die dazu führt, so etwas wie auto zu verwenden: so lange es (typ-)sicher ist, so wenig denkarbeit wie möglich zu verlangen - und dann kann der compiler es einfach so machen, dass es passt/geht. wenn etwas, was der programmierer will, aber unsicher, gefährlich, unüberlegt oder dumm ist, dann (nicht verbieten, wie in anderen sprachen) zumindest hässlich und aufwändig machen ("
reinterpret_cast")das prinzip ist: je mehr tippen man muss, desto länger kann man sich die frage stellen "will ich das wirklich? gibt es nicht eine bessere alternative?"
-
Nein, sehe ich nicht ganz so. Also falls ich dich richtig verstanden habe.
MMn. ist der wichtigere Punkt wirklich dass man speziell nur bestimmte Dinge erlauben kann, und nicht dass es hässlich und viel zu tippen ist.Mir geht z.B. sogar noch ein Cast ab:
implicit_cast.
Alaimplicit_cast<MyInterface*>(p)->MyInterfaceFunction(); // statt MyInterface* pmi = p; pmi->MyInterfaceFunction();Also einen Cast der nur Konvertierungen erlaubt die als implizite Konvertierungen erlaubt wären.
static_castwürde hier zu viel erlauben.implicit_castwäre hier mMn. also nicht besser weil es länger zu tippen ist alsstatic_cast, sondern weil es mehr unerwünschte Casts verbietet.