Dynamischer Type-Cast
-
Suchst du hier eventuell die virtuellen Funktionen?
class foo { public: virtual void func() { cout << "foo" << endl; } }; class bar : public foo { public: virtual void func() { cout << "bar" << endl; } }; // ... foo *ptr = new bar; ptr->func(); // Ausgabe: barSonst ergibt das nämlich nicht viel Sinn. Was hast du davon, wenn du den Pointer in einen Typen umwandeln kannst, den du gar nicht kennst? Entweder du willst auf Member zugreifen, die im Basisklaseninterface definiert sind (-> virtuelle Funktionen) oder auf typspezifische Member, die du aber gar nicht kennen kannst.
-
Braunstein schrieb:
Erstmal: Ein fehlgeschlagener dynamic_cast auf einen Pointer wirft keine Exception sondern gibt 0 zurück.
Zitat aus "C++ Primer":
(...), when a cast fails, it throws a std::bad_cast exception.
Hört sich für mich schon so an...
Der Hintergrund ist: Ich habe ein Frame, dessen Konstruktor einen Owner (TComponent) übergeben bekommt. Diesen Owner speichere ich entsprechend gecastet in einer privaten Eigenschaft, da ich bestimmte Komponenten von ihm verwende (und bei ihm voraussetze). Wird das Formular jetzt woanders verwendet, möchte ich nur die Definition der privaten Eigenschaft ändern, sonst nix. In dem Konstruktor möchte ich also den Owner-Parameter auf den Typ von PrivateOwner casten um ihn dann in selbigen zu speichern.
-
Wenn das schon in deinem Buch stand, hattest du doch bereits eine Antwort auf deine Frage.
Die Exception wird jedoch nur bei Referenzen geworfen, bei Zeigern liefert dynamic_cast eben einfach 0.
-
class virtUal { public: virtUal(int a) : mi(a) {} virtUal ~virtUal(); virtual void virt() = 0; int i() {return mi;} protected: int mi; }; class ab1 : public virtUal { public: ab1(int i) : virtUal(i) {}; void virt() { mi = 1000; } }; class ab2 : public virtUal { public: ab2(int i) : virtUal(i) {}; void virt() { mi = 0; } }; int main() { virtUal * v1 = new ab1(5); ab1 * a = dynamic_cast<ab1*>(v1); // <<-- kein Nulpointer ab2 * a2 = dynamic_cast<ab2*>(v1); // <<-- Nulpointer ab1 a3 = dynamic_cast<ab1>(*v1); // <<-- gültiges objekt ab2 a4 = dynamic_cast<ab2>(*v1); // <<-- crash .. std::bad_cast exception }Du könntest nach allen möglichen abgeleiteten Klassen Probe-casten und das nehmen das keinen Nullpointer zurückgibt...
-
@Heimelchen
bezüglich der Exception siehe Standard 5.2.7 9The value of a failed cast to pointer type is the null pointer value of the required result type. A failed cast to
reference type throws bad_cast (18.5.2).Ich würde dir vorschlagen aus deinem Frame eine Template Klasse zu machen wenn es denn wirklich nötig ist den genauen Typ zu können.
Ich frage mich allerdings warum das nötig ist. Wenn du den genauen Typ des Owners wisse willst, dann willst du vielleicht auf Membervaraiblen oder -funktionen zugreifen die nur da existieren.
Dann hättest du aber auch unterschiedlichen Code je nach Owner-Typ. Das sieht mir dann eher weider danach aus einfach speziell dafür angepasste Frames zu nehmen.
-
Ich glaube, bevor ich da einen riesen Aufwand betreibe, finde ich mich lieber damit ab, im Änderungsfall an zwei Stellen einen neuen Typ eingeben zu müssen... :-7
-
Sofern der Typ von MyPointer wirklich ein Zeiger auf den konkreten Typ ist, was spricht gegen die inplace Lösung?
-
Hachja, es lebe die Frickelei

#include <typeinfo> #include <iostream> #include <string> class X { public: virtual std::string GetType() { return typeid(*this).name(); } }; class A : public X { }; class B : public X { }; int main() { X *a = new A; std::cout << a->GetType() << std::endl; // vom Typ "class A" delete a; a = new B; std::cout << a->GetType() << std::endl; // vom Typ "class B" delete a; }
-
Du erzeugst wegen des fehlenden virtuellen Destruktors in deinem Beispiel undefiniertes Verhalten.
-
Ist das hier wirklich der Fall?
Keine dieser Klassen hat irgendwelche Membervariablen.
-
Braunstein schrieb:
Ist das hier wirklich der Fall?
Keine dieser Klassen hat irgendwelche Membervariablen.Aus dem C++-Standard:
5.3.4/3 schrieb:
In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.73)
In der Praxis wird es vielleicht wegen der fehlenden Member funktionieren, aber es besteht keine Garantie. Ausserdem ist es sehr schlechter Stil, polymorph genutze Klassen ohne virtuellen Destruktor auszustatten. Nicht zuletzt habe ich das angemerkt, weil ich kürzlich einige Stunden wegen genau diesem idiotischen Fehler debuggt habe.

-
Vielen Dank für die Information.
Ich habe sowas auch noch nie gemacht. Es gibt aber bei uns Kollegen die meinen das sei kein Problem. Deswegen die Frage.