Dynamischer Type-Cast



  • 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 9

    The 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.


Anmelden zum Antworten