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 Input Objekt niemals ein ChoiceInput Objekt 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 Slicing auf, 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.


  • Administrator

    Input input = inputTable.value(objectName);
    

    Hier kopierst du das Objekt und verlierst dabei alle Informationen über ChoiceInput . Du hast effektiv nun ein Input Objekt.

    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 ein Input Objekt.

    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 ein Input Objekt.

    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?)


Anmelden zum Antworten