Typbestimmung zur Laufzeit



  • Hi

    weiß jemand wie ich bei einem Up-cast die richtige Klasse herausfinden kann? Problem ist folgendes: Ich hab eine map<POINT, cObj*> in der alle möglichen Objekte stehen. Hier ein Ausschnitt aus der Hierarchie:

    cObj
    |
    +-cPlanet
    | |
    | +-cPlanetClass1
    | |
    | +-cPlanetClass2
    |
    +-Ship
    | |
    | +-cFighter
    | |
    | +-cBomber

    Gibt es eine Möglichkeit herauszufinden von welchem Typ das zurückgegebene Objekt map[myPoint] ist? Ich kenne die Möglichkeit:

    if( dynamic_cast <cPlanetClass1*> (cObj*) )
    	// ist cPlanetClass1
    else if( dynamic_cast <cPlanetClass2*> (cObj*) )
    	// ist cPlanetClass2
    else if( dynamic_cast <cFighter*> (cObj*) )
    	// ist cFighter
    else if( dynamic_cast <cBomber*> (cObj*) )
    	// ist cBomber
    

    gibt es davon abgesehen eine andere (vollautomatische) Möglichkeit das gleiche Ziel zu erreichen? Ursprünglich dachte ich an sowas wie

    typeid( map[myPoint] )
    

    bis ich fesgestellt habe, dass das eben nicht funktioniert. Aber vielleicht irgendwas ähnliches?

    MfG
    Ben



  • Man könnte noch virtuelle Methoden benutzen, oder typeid in verbindung mit maps, aber das ist alles nicht das wahre. Der Sinn von polymorphismus ist doch gerade, dass man nicht weiß welche Klasse es ist. Man benutzt virtuelle Funktionen um die richtige Methode aufzurufen, wenn man mehr wissen muss aht man meiner meinung nach einen designfehler...
    Wenn du aber mehr auf multidispatching ausbist (zum beispiel unterschiedliche Kollisionsfunktionen aufrufen willst) hätte ich da noch was anderes für dich 😃



  • gibt es davon abgesehen eine andere (vollautomatische) Möglichkeit das gleiche Ziel zu erreichen? Ursprünglich dachte ich an sowas wie [...]

    Ja. Dynamisches Binden von Methoden.



  • Falls dir das unbekannt ist:

    class basis
    {
    public:
        virtual void name(){cout<<"basis";};
    };
    
    class abgl1
        :public basis
    {};
    
    class abgl2
        :public basis
    {
    public:
        virtual void name(){cout<<"abgl2";};
    };
    
    class abgl3
        :public basis
    {
    public:
        virtual void name(){cout<<"abgl3";};
    };
    
    int main()
    {
        basis pb1=new basis;
        basis pb2=new abgl1:
        basis pb3=new abgl2;
        basis pb4=new abgl3;
        cout<<pb1->name()<<endl;    //basis
        cout<<pb2->name()<<endl;    //auch basis! Funktion nicht überschrieben
        cout<<pb3->name()<<endl;    //abgl2
        cout<<pb4->name()<<endl;    //abgl3
        return 0;
    };
    

    Geht nat. nicht nur mit simplen namensfunktionen...



  • wenn man nesss(arrgh 3s sehen scheisse aus...nesses? bäääh, ich hasse grammatik) vorschlag weiterverfolgt könnte man auf sowas kommen:

    class Base{
        private:
            virtual std::size_t id()=0;
    };
    class Derived1{
        private:
            virtual std::size_t id(){return 1;}
            void dosth1(){...}
    };
    class Derived2{
        private:
            virtual std::size_t id(){return 2;}
            void dosth2(){...}
    };
    class Derived3{
        private:
            virtual std::size_t id(){return 3;}
            void dosth3(){...}
    };
    
    void foo(Base* b){
        switch Base->id(){
            case 1:
                ((Derived1*)b)->dosth1();
            case 2:
                ((Derived1*)b)->dosth2();
            case 3:
                ((Derived1*)b)->dosth3();
        }
    }
    

    benutzen kann man das dann so:

    Base* b1=new Derived1;
    Base* b2=new Derived2;
    Base* b3=new Derived3;
    foo(b1);
    foo(b2);
    foo(b3);
    

    das ganze hat dann eine konstante ausführungszeit, hat aber als nachteil, dass das klassendesign geändert werden muss.

    alternative:

    void foo(Base* b){
        if(typeid(b)==typeid(Derived1){
            ((Derived1*)b)->dosth1();
        }
        if(typeid(b)==typeid(Derived2){
            ((Derived2*)b)->dosth2();
        }
        if(typeid(b)==typeid(Derived3){
            ((Derived3*)b)->dosth3();
        }
    }
    

    das hat dann eine lineare ausführungszeit, das klassendesign leidet aber nicht drunter.



  • @Optimizer: Wie würde das dann aussehen, hast du ein beispiel?



  • Er meint virtuelle Funktionen!
    Das was hier schon die ganze Zeit diskutert wird. Wenn du je nach dem Typ eines Objektes eine Funktion Aufrufen willst, reicht das. Wenn nicht, sieh dir otzes post oder das hier (automatisierung der 2. Variante 😃 ) an!


Anmelden zum Antworten