operator== in Vererbungshierarchie...



  • Und wie würde dein ==-Operator aussehen?
    So wie bei Eisflamme? Dann hättest du ja dynamic_cast und typeid.
    Warum ist das 'die richtige vorgehensweise'?



  • Jockelx schrieb:

    Und wie würde dein ==-Operator aussehen?

    Den gäbe es gar nicht.

    So wie bei Eisflamme? Dann hättest du ja dynamic_cast und typeid.
    Warum ist das 'die richtige vorgehensweise'?

    Kein typeid, nur der dynamic cast.



  • Kein operator== aber dafür compareTo, wieso? Und ist dynamic_cast nicht teurer als typeid, das ergab meine bisherige Recherche jedenfalls.



  • Weils bisher noch nicht genannt wurde werfe ich nochmal Double Dispatch in den Raum. Das wäre zumindest eine Lösung ohne dynamic_cast und typeid . Ob sie besser/schneller ist weiß ich nicht.



  • Ah, mein compareTo ist auch nicht ganz richtig, hier kommt die richtige Variante.

    Das Problem mit dem typeid ist ja, dass man damit nur exakt gleiche Klassen testen kann. Das kann gewollt sein aber oft verhindert das sinnvolles Subclassing.

    Und da die compare Funktion ja öffentlich (protected) ist, kann man da Fehler machen wenn ich die aufrufe obwohl ich den op== verwenden sollte.

    Operatoren mit virtuellen verhalten mage ich persönlich nicht, deshalb habe ich eine compareTo funktion für die polymorphen Vergleiche. Aber prinzipiell kann man hier auch den op== verwenden.

    class Base {
    public:
            Base(int a) : value(a) {}
    
            virtual bool compareTo(Base const& other) const {
                    return this->value == other.value;
            }
    
    private:
            int value;
    };
    
    class Derived : public Base {
    public:
            Derived(int a, int b) : Base(a), value(b) {}
    
            virtual bool compareTo(Base const& other) const {
                    Derived const* p = dynamic_cast<Derived const*>(&other);
                    if(!p) return Base::compareTo(other);
                    return value==p->value && Base::compareTo(other);
            }
    private:
            int value;
    };
    
    #include <iostream>
    
    using namespace std;
    
    int main() {
            Base b(1);
            Derived x(1,1);
            Derived y(2,1);
    
            cout<< "b==x: " << b.compareTo(x) << endl;
            cout<< "x==b: " << x.compareTo(b) << endl;
            cout<< "b==y: " << b.compareTo(y) << endl;
            cout<< "y==b: " << y.compareTo(b) << endl;
            cout<< "x==y: " << x.compareTo(y) << endl;
            cout<< "y==x: " << y.compareTo(x) << endl;
            cout<< "b==b: " << b.compareTo(b) << endl;
            cout<< "x==x: " << x.compareTo(x) << endl;
            cout<< "y==y: " << y.compareTo(y) << endl;
    }
    


  • Jockelx schrieb:

    kurze_frage schrieb:

    Es stellt sich jedoch schon die Frage, warum sollte ich einen Fisch auf Gleichheit mit einer Katz vergleichen nur weil beides Lebewesen sind.

    Weil du vielleicht einen Fisch hast, von dem du wissen willst, ob er in einem Lebewesen-Container enthalten ist.

    Hä? Was hat der Lebewesen-Container mit einer Katze zu tun??
    fisch == katze muss wohl false sein.

    lebewesen == fisch und
    fisch == lebewesen müssen beide false ergeben. Objekt slicing beim Vergleich? Wo soll das sinnvoll sein?



  • Verstehe deine Frage nicht. Mit slicing hat das 0,0 zu tun.
    fisch == katze = false wird ja gerade durch das typeid erreicht.

    Pseudocode:

    class Tier
    {
      string farbe;
    };
    class Fisch : Tier;
    class Katze : Tier;
    
    vector<Tier*> tiere = {new Tier("gelb"), new Fisch("pink"), new Katze("lila")};
    Tier* fischpink= new Fisch("pink");
    Tier* fischlila= new Fisch("lila");
    for(Tier* t : tiere)
    {
      if(*t == *fischpink) cout << "Jau, pinken Fisch gibts schon";
      if(*t == *fischlila) cout << "Jau, lila Fisch gibts schon";
    }
    //Out: Jau, fischpink gibts
    


  • Aufpassen: nicht jede Vererbung erzeugt etwas komplett anderes. Klar koennen Fisch und Katze unterschiedliche Tiere sein, wenn ich aber nach dem Haustier mit dem Namen "Bello" suche, ist mir das aber egal ob es ein Fisch oder eine Katze ist.

    Auch kommt es ja oft vor dass man Vererbt um Funktionalitaet hinzuzufuegen. Rein auf die typeid zu testen limitiert solche Situationen. Aber Klassen Design ist immer auf einen speziellen Fall anzuwenden und es gibt kaum Allgemein gueltige Aussagen.



  • Mmh!? Schön, aber behauptet nur niemand!
    Eisflamme hat ein bestimmtes Scenario beschrieben und gefragt und wie man das 'schön' umsetzt.



  • Jockelx schrieb:

    Verstehe deine Frage nicht. Mit slicing hat das 0,0 zu tun.
    fisch == katze = false wird ja gerade durch das typeid erreicht.

    Pseudocode:

    class Tier
    {
      string farbe;
    };
    class Fisch : Tier;
    class Katze : Tier;
    
    vector<Tier*> tiere = {new Tier("gelb"), new Fisch("pink"), new Katze("lila")};
    Tier* fischpink= new Fisch("pink");
    Tier* fischlila= new Fisch("lila");
    for(Tier* t : tiere)
    {
      if(*t == *fischpink) cout << "Jau, pinken Fisch gibts schon";
      if(*t == *fischlila) cout << "Jau, lila Fisch gibts schon";
    }
    //Out: Jau, fischpink gibts
    

    ja so ungefähr, wenn du dich jetzt selber darum kümmerst das der Fisch ein Fisch ist, was so sein sollte denn warum sollte ein Fisch für dich testen das die Katze kein Fisch ist, dann gibts ganz normale == operatoren die Eigenes vergleichen und Reste an die Basis zum vergleich weiterleiten.

    for(Tier* t : tiere)
    {
      if (artgleich(t, fischpink) {
        if(*t == *fischpink) cout << "Jau, pinken Fisch gibts schon";
        if(*t == *fischlila) cout << "Jau, lila Fisch gibts schon";
      }
    }
    


  • Ich verstehe den Vorteil des externen Vergleichs auf Typgleichheit nicht. Könntest du den nochmal erläutern?



  • Eisflamme schrieb:

    Ich verstehe den Vorteil des externen Vergleichs auf Typgleichheit nicht. Könntest du den nochmal erläutern?

    bezahle nur für das was du brauchst dort wo du es brauchst.

    Ich sehe grade das das cast im Beispiel oben fehlt, so ist es komplett

    for(Tier* t : tiere)
    {
      Fish* f = dynamic_cast<Fish>(t);
      if (f) {
        if(*f == *fischpink) cout << "Jau, pinken Fisch gibts schon";
        if(*f == *fischlila) cout << "Jau, lila Fisch gibts schon";
      }
    


  • Mir ist jetzt auch nicht klar, worauf du hinauswillst.


Anmelden zum Antworten