Klasse eines Objekts herausfinden



  • KmG schrieb:

    Wie kann ich das machen, ohne dem jeweiligen Object ein Attribut zu geben.

    Mit einer virtuellen Funktion.
    Willst Du dann ein switch oder if dranbasteln, was anhand des wirklichen Typs des Objekts unterschiedliche Sachen macht?



  • Ich will die Liste durchgehen, und dann die "richtigen" Objekte in ne andere Liste stecken. Also wir da schon nen if bzw. switch dahinter kommen.

    Die virtuelle Methode packe ich dann die Klasse Auto oder? Ich weiß noch nicht genau, was die virtuelle Methode dann machen soll. Auf jeden Fall soll die ja dann mir etwas zurückgeben, wenn ich ein Element aus meiner Liste hole und die Methode von dem Element aufrufe. Hättest du vllt. nen Code Beispiel?

    LG
    KmG



  • typeid brauchst du deswegen immer noch nicht. Eher dynamic_cast , falls es wirklich nicht mit virtuellen Funktionen geht.

    Was sind die "richtigen" Objekte? Besitzen die eine gemeinsame Eigenschaft, die du eventuell auch sonst irgendwo brauchst? Falls ja, können sich virtuelle Funktionen bereits lohnen.



  • Die richtigen Objekte sind z.B. blaue BMWs, dafür wollte ich erst gucken, ob das Objekt ein BMW ist und dann im zweiten Schritt, ob der BMW blau ist. Aber es wird vermutlich kein Attribut geben, was den BMW eindeutig von den anderen Autos unterscheidet.

    Wie wäre der Ansatz mit dynamic_cast ? Haben casts Rückgabe Werte?
    Mit typeid hat mir in dem Zusammenhang wenig geholfen, die Id war immer Auto egal obs nen BMW oder nen VW war.

    Gruß
    KmG



  • KmG schrieb:

    Wie wäre der Ansatz mit dynamic_cast ? Haben casts Rückgabe Werte?

    Ja, wobei Cast-Operatoren keine Funktionen im eigentlichen Sinn sind.

    KmG schrieb:

    Mit typeid hat mir in dem Zusammenhang wenig geholfen, die Id war immer Auto egal obs nen BMW oder nen VW war.

    Du sollst die Auto -Klasse auch polymorph machen und den dynamischen Typen abfragen.

    Mit dynamic_cast :

    Auto* a = new BMW();
    
    if (BMW* b = dynamic_cast<BMW*>(a))
    {
       // arbeite mit BMW b
    }
    
    delete a;
    

    Aber besonders elegant sind Typunterscheidungen nicht. Benutze sie nur, wenn du wirklich nichts mit virtuellen Funktionen erreichen kannst.



  • virutelle Funktionen sind doch Funktionen, die durch das Kindelement überschrieben werden und ich dann später dennoch aufrufen kann, deswegen versteh ich nicht ganz, was die dann herausbekommen soll, welches Element es ist. Dann müsste ich ein Atribut in Auto einführen, dass mir sagt, was für ein Auto es ist oder?

    Ich kann mir gerade nicht ganz vorstellen, wie die virutelle Methode aussehen soll.

    Vielen Dank für die Hilfe bis jetzt schon.

    LG
    KmG



  • Du könntest ein datenelement mit dem namen speichern und dann abfragen. Sowieso hat jedes Auto eine Marke und eine Farbe, ansich gehören diese Atribute in die Basisklasse, dort brauchst du dann nur noch get-funktionen die es abfragen, und zum Beispiel einen String zurückliefern.

    Pseudo-Code!

    class Auto
    {
    private:
        std::string marke;
        std::string farbe;
    public:
        Auto(std::string Marke, std::string Farbe)
         :marke(Marke),farbe(Farbe) {}
    
        std::string getFarbe() {return this->farbe;}
        std::string getMArke() {return this->marke;}
    
        //Sonstige Funktionen
    };
    
    class BMW :public Auto
    {
    public:
        BMW(std::string farbe)
        :Auto("BMW",farbe) {}
    
        // sonstiges
    };
    

    Nun kannst du einfach beim sortieren die Funktionen aufrufen und vergleichen:

    auto1.getFarbe(); auto2.getMarke();
    


  • Da es denke ich noch nicht erwähnt wurde: du kannst in einen std::vector<Auto> keinen BMW reinstecken.
    Du kannst es versuchen, aber der BMW wird zu einem einfachen Auto verkrüppelt wenn du es versuchst. D.h. im std::vector<Auto> ist es kein BMW mehr. Das nennt man im Übrigen "slicing".
    Die Klasse ist daher immer Auto, wenn es aus dem std::vector<Auto> kommt.

    Was natürlich geht, ist einen std::vector<Auto*> zu machen, und da drinnen Zeiger auf Autos zu speichern. Die bleiben dann auch was sie sind.



  • KmG schrieb:

    virutelle Funktionen sind doch Funktionen, die durch das Kindelement überschrieben werden und ich dann später dennoch aufrufen kann, deswegen versteh ich nicht ganz, was die dann herausbekommen soll, welches Element es ist. Dann müsste ich ein Atribut in Auto einführen, dass mir sagt, was für ein Auto es ist oder?

    Ich kann mir gerade nicht ganz vorstellen, wie die virutelle Methode aussehen soll.

    Nein. Ein solches Attribut solltest du nicht einführen. Bei einem sauberen Design sollte es egal sein, um was für ein Auto es sich handelt. Das Design sollte so sein, dass die Basisklasse die Funktionen bereit stellt, die du brauchst. Nicht mehr und nicht weniger.

    Beispiel:
    Mache sowas nicht:

    if (dynamic_cast<BMW*>(automobil)) {
       cout<<"Es ist ein BMW"<<endl;
    }
    if (dynamic_cast<VW*>(automobil)) {
       cout<<"Es ist ein VW"<<endl;
    }
    

    Statt dessen machst du sowas:

    class Auto {
       public:
          virtual void typ_ausgeben() = 0;
    };
    
    class BMW {
       public:
          void typ_ausgeben() {
             cout<<"Es ist ein BMW"<<endl;
          }
    };
    
    class VW {
       public:
          void typ_ausgeben() {
             cout<<"Es ist ein VW"<<endl;
          }
    };
    
    // Aufruf
    automobil->typ_ausgeben();
    

    Ich hoffe, das macht das ganze klar.



  • Ja, aber wenn es nachher auf sowas hinausläuft...

    class Auto
    {
        public:
            virtual std::string GetType() const = 0;
    };
    
    class BMW : public Auto
    {
        public:
            virtual std::string GetType() const
            {
                return "BMW";
            }
    };
    
    class Peugeot : public Auto
    {
        public:
            virtual std::string GetType() const
            {
                return "Peugeot";
            }
    };
    
    int main()
    {
        Auto* a = new Peugeot;
        std::string type = a->GetType();
    
        if (type == "BMW")
        {
            // ...
        }
        else if (type == "Peugeot")
        {
            // ...
        }
        delete a;
    }
    

    ...kann man gerade so gut dynamic_cast einsetzen, weil man so keine virtuellen Methode definieren muss, weil es keine Konventionen (welches Format hat der String) zu beachten gibt und weil die Typunterscheidung, die durch virtuelle Funktionen gerade zu verhindern wäre, in beiden Fällen unvermeidlich bleibt.


Anmelden zum Antworten