[dynamic_cast] Wer hat recht?



  • Hallo,

    ich hab hier ein kleines Problem mit dynamic_cast. Zur veranschaulichung ein "etwas" vereinfachtes Beispiel:

    Klassenhirachie: Klasse C ist von Klasse B abgeleitet und Klasse B von Klasse A. Polymorphismus etc. ist alles korrekt implementiert. Nun folgender Code (vereinfachtes Beispiel):

    C c;
    A* a = &c;
    B* tmp = dynamic_cast<B*>(a);
    

    Mit dem Microsoft Compiler bekomme ich eine gültigen Zeiger zurück. Kompilier ich den Code hingegen unter Linux mit dem gcc bekomme ich einen Nullpointer zurück. Preisfrage: Welcher Compiler arbeitet richtig?



  • BugJoe schrieb:

    Polymorphismus etc. ist alles korrekt implementiert.

    Heisst? Hat Klasse A mindestens eine virtuelle Funktion?



  • Richtig



  • BugJoe schrieb:

    Zur veranschaulichung ein "etwas" vereinfachtes Beispiel:

    Klassenhirachie: Klasse C ist von Klasse B abgeleitet und Klasse B von Klasse A. Polymorphismus etc. ist alles korrekt implementiert.

    Wenn ich es richtig interpretiere kann man dies wie folgt nachstellen:

    class A
    {
        public:
            virtual ~A() {};
    };
    
    class B : public A
    {
    };
    
    class C : public B
    {
    };
    
    int main()
    {
        C c;
        A* a = &c;
        B* tmp = dynamic_cast<B*>(a);
    }
    

    BugJoe schrieb:

    Mit dem Microsoft Compiler bekomme ich eine gültigen Zeiger zurück. Kompilier ich den Code hingegen unter Linux mit dem gcc bekomme ich einen Nullpointer zurück. Preisfrage: Welcher Compiler arbeitet richtig?

    In diesem Fall würde ich sagen, das der Microsoft Compiler recht hat, Da c sowohl ein A, B als auch C ist.

    cu André



  • asc schrieb:

    In diesem Fall würde ich sagen, das der Microsoft Compiler recht hat, Da c sowohl ein A, B als auch C ist.

    Sofern deine Annahme, dass es eine public Vererbung ist hast du Recht.



  • drakon schrieb:

    Sofern deine Annahme, dass es eine public Vererbung ist hast du Recht.

    Die Annahme muss ich einfach mal machen, solange keine anders lautenden Informationen existieren (Ich habe absichtlich ein Beispiel gepostet, so das der OT ggf. noch etwas anmerken kann was in seiner Beschreibung fehlt) ;p



  • Ja richtig, es sind überall public Vererbungen. Sorry, das hab ich ganz vergessen zu erwähnen.

    PS: Achso, vielleicht sollte ich erwähnen, dass B und C ebenfalls virtuelle Methoden besitzen. Tut das was zur Sache?



  • BugJoe schrieb:

    PS: Achso, vielleicht sollte ich erwähnen, dass B und C ebenfalls virtuelle Methoden besitzen. Tut das was zur Sache?

    Wichtig ist nur das es eine VTable bereits in der untersten Basisklasse gibt. Dies ist in der Regel bereits durch den ohnehin sinnvollen virtuellen Destruktor gegeben.

    cu André



  • Ich hab gerade mit erstaunen feststellen müssen, dass das obige Minimalbeispiel mit dem gcc korrekt funktioniert. Jetzt stellt sich für mich natürlich die Frage was bei einem dynamic_cast noch schief gehen kann damit ein Nullpointer zurück geliefert wird?

    • RTTI ist aktiviert (wobei ich denke, dass der gcc sowieso meckern würde wenn RTTI nicht aktiviert ist und man irgendwo ein dynamic_cast oder typeid verwendet)
    • An der Vererbungshirachie kann ich keine Fehler entdecken
    • Polymorphismus wird korrekt verwendet
    • Und das verwirrendste...mit dem M$ Compiler funktioniert es auch

    Kann es sein, dass der gcc (ich verwende Version 4.1.2) hier einen Bug hat?



  • Da ich auch der Meinung bin, der msvc hat recht und ich nicht glauben kann, daß der gcc so etwas einfaches falsch macht, habe ich es gerade mal selbst ausprobiert. Also der Code von asc liefert bei mir mit gcc unter Linux richtgerweise einen Zeiger ungleich 0.

    Es wäre einfacher, wenn in der Originalfrage bereits ein vollständiges Beispiel dabei wäre. @BugJoe: könntest Du ein Beispiel liefern, was unter Linux nicht korrekt funktioniert? Ich glaube, Du hast da ein anderes Problem.



  • BugJoe schrieb:

    [*]Und das verwirrendste...mit dem M$ Compiler funktioniert es auch[/list]

    LOL! MS-Bashing kann man sich beim C++-Compiler sparen.



  • tntnet schrieb:

    Da ich auch der Meinung bin, der msvc hat recht und ich nicht glauben kann, daß der gcc so etwas einfaches falsch macht, habe ich es gerade mal selbst ausprobiert. Also der Code von asc liefert bei mir mit gcc unter Linux richtgerweise einen Zeiger ungleich 0.

    Es wäre einfacher, wenn in der Originalfrage bereits ein vollständiges Beispiel dabei wäre. @BugJoe: könntest Du ein Beispiel liefern, was unter Linux nicht korrekt funktioniert? Ich glaube, Du hast da ein anderes Problem.

    Ja, wie schon geschrieben, ich kann das Beispiel bei mir auch korrekt zum laufen bringen. Ich muss mal schauen wie ich den Code hier aufbereiten kann, denn veröffentlichen darf ich ihn auf keinen Fall, sonst bin ich zwei Köpfe kürzer.



  • BugJoe schrieb:

    Ja, wie schon geschrieben, ich kann das Beispiel bei mir auch korrekt zum laufen bringen. Ich muss mal schauen wie ich den Code hier aufbereiten kann, denn veröffentlichen darf ich ihn auf keinen Fall, sonst bin ich zwei Köpfe kürzer.

    Das musst/solltest du auch nicht. Probier einfach das Beispiel auf den kleinsten (nicht funktionierenden) Nenner bringen. Dann findest du meist eh heraus, wo genau das "Problem" liegt. Wobei ich mal eher vermute, dass es nicht am Code direkt liegt. Da GCC und VC recht respektable Compiler sind werden die kaum einen Unterschied haben. Aber ausgeschlossen ist natürlich nichts. Unwahrscheinlich, aber durchaus möglich. 😉



  • also mit dem gcc 4.1.x hatt eich bisher keine Probleme. Beim 4.2er gab's teils Probleme mit "this" Zeigern (Thread hie ruím Forum). Der 4.3er arbeitet einwandfrei. Ich würde das Beispiel nochmal mit einer anderen Compiler Version testen. Aber an sich sollte das jeder gcc schlucken und korrekt interpretieren


Anmelden zum Antworten