Dynamic cast can never succeed: Wieso?
-
Ich habe ein Hashtable (QHash) in dem Objekte vom Typ Input sind.
Input hat verschiedene Unterklassen, unter anderem ChoiceInput (zumindest ist das so gedacht).Jetzt möchte ich gerne wissen ob ein bestimmtes Objekt aus dem Hashtable ein Choiceinput ist und habe diesen Code dafür geschrieben:
if (inputTable.contains(objectName)) { Input input = inputTable.value(objectName); ChoiceInput *choiceInput = dynamic_cast<ChoiceInput*>(&input); if (choiceInput) { //do stuff with choiceInput } }Der compiler sagt mir jetzt dass dieser Cast nie erfolgreich sein kann, was habe ich falsch gemacht?
Die Klasse habe ich so definiert:
class ChoiceInput: public Input
und in der Input-Headerdatei habe ich den Dekonstruktor virtual gemacht.
-
Weil ein
InputObjekt niemals einChoiceInputObjekt sein, nur umgekehrt.Edit:
if (inputTable.contains(objectName)) { Input input = inputTable.value(objectName); ChoiceInput *choiceInput = dynamic_cast<ChoiceInput*>(&input); if (choiceInput) { //do stuff with choiceInput } }In Zeile 2 kopierst du den Inhalt aus der Hash Map, dabei tritt
Object Slicingauf, d.h. alle Informationen der abgeleiteten Klasse gehen verloren und du erhälst nur die Informationen der Basisklasse. Anschließend versuchst du die verloren gegangenen Informationen wieder dazuzucasten, was natürlich nicht gelingen kann.
-
Input input = inputTable.value(objectName);Hier kopierst du das Objekt und verlierst dabei alle Informationen über
ChoiceInput. Du hast effektiv nun einInputObjekt.Siehe auch: Object Slicing.
Grüssli
-
Dravere schrieb:
Input input = inputTable.value(objectName);Hier kopierst du das Objekt und verlierst dabei alle Informationen über
ChoiceInput. Du hast effektiv nun einInputObjekt.Siehe auch: Object Slicing.
Grüssli
Danke für die schnelle Antwort, das erklärt das Problem!
Hast Du eine Idee wie ich meine Anforderung anders umsetzen könnte?
-
Dravere schrieb:
Input input = inputTable.value(objectName);Hier kopierst du das Objekt und verlierst dabei alle Informationen über
ChoiceInput. Du hast effektiv nun einInputObjekt.Siehe auch: Object Slicing.
Grüssli
Wahrscheinlich auch schon vorher in der HashMap.
-
Jockelx schrieb:
Wahrscheinlich auch schon vorher in der HashMap.
Ja, müsste dann ja, QHash habe ich ja mit <QString, Input> definiert.
Argh!
Gibt es denn eine Möglichkeit wie ich eine Anzahl von verschiedenen Unterklassen in einem Hashtable (o.ä.) unterbringen kann?
In Java gibt es das Object-Slicing nicht, bislang war mir das neu.
-
Das Design ist so eh völlig verkackt. (Wie so gut wie immer wenn man irgendwo dynamic_cast sieht.)
Entweder du willst das verhalten des Objekts beeinflussen, dann nimm eine virtuelle Funktion, oder du willst eine Art Typinformation abspeichern, dann nimm halt ein enum. Aber das da ist Quatsch.
-
simon.hain schrieb:
Gibt es denn eine Möglichkeit wie ich eine Anzahl von verschiedenen Unterklassen in einem Hashtable (o.ä.) unterbringen kann?
Ja, du musst Zeiger (oder smart-Pointer) auf die Objekte ablegen, denn die sind stets gleich gross und nix wird 'gesliced'.
-
Jockelx schrieb:
Ja, du musst Zeiger (oder smart-Pointer) auf die Objekte ablegen, denn die sind stets gleich gross und nix wird 'gesliced'.
Edit:
Alles klar, hab es hinbekommen, bei allen mutable classes habe ich den Pointer, jetzt funktioniert es so wie ich mir das vorgestellt hab.
(auch das dynamic_cast, wieso das böse ist verstehe ich allerdings nicht, dafür jetzt ein visitor pattern zu bauen ist doch übertrieben?)