operator = in abgeleiteter Klasse



  • damit wär das auch geklärt 🙂



  • Warum wäre es eigentlich vorteilhaft diesen Operator Global zu definieren?



  • wieso nicht:

    bool Variable::operator ==(const AbstractTerm &other) const { 
    	Variable *p=dynamic_cast<Varaible *>&other; 
    	return p!=0 && mName==p->mName;
    }
    

    Müsste man nur noch global definieren.



  • Du könntest aber trotzdem die dynamic_casts umgehen.

    Ich stell mir da etwas in folgende Richtung vor, habs
    jetzt nicht getestet, mit ein wenig abänderung müsste
    das aber schon hinhaun.

    class AbstractTerm
    {
        protected:
            // ich habs jetzt mal protected gesetzt um die öffentliche 
            // Schnittstelle nicht zuzumüllen. könntest ja dann über nen
            // globalen friend operator == aufrufen
            virtual bool equals(const AbstractTerm& other) const
            {    return other.equals(*this);    }
    
        // mindestens noch eine rein virtualle Methode, damit die Instanziierung
        // von AbstractTerm verhindert wird, sonst würde die Methode oben zu ner
        // Endlosrekursion führen können
    
        // ..
    };
    
    class Variable : public AbstractTerm
    {
        protected:
            using AbstractTerm::equals;
    
            virtual bool equals(const Variable& other) const
            {    return name == other.name;    }
    };
    

    Das müsste hinhaun, da bei nem Aufruf von base->method() in der Methode
    selbst *this der dynamische Typ von base is (sofern method virtuell ist
    und überschrieben wurde).

    Tankian



  • die variante ist gut 🙂
    dann ließe sich auch ein globaler op== gut implementieren:

    friend bool operator==(AbstractTerm& first,AbstractTerm& second){
        return first.equals(second);
    }
    

    //edit anzumerken ist nur, dass einige compiler damit nicht klarkommen.



  • @tooler

    - Um die Anzahl der Memberfunktionen, die Zugriff auf die Repräsentation des Objekts haben, zu minimieren.

    - Damit du durch implizites Casting den Typ Variable auch mit Buildins vergleichen kannst. Z.B

    void f(Variable x) {
    	3==x;
    }
    


  • na, das ist nicht der grund
    du brauchst das dafür:

    bool operator==(class1&,class2&);
    bool operator==(class2&,class1&);

    du müsstest ansonsten 2 klassen mit den operatoren zumüllen, und das ist schlecht, sobald du vielleicht auf eine Klasse nicht zugreifen kannst um sie zu verändern(zb in dlls)



  • @otze:

    Na, in diesem Fall lag dann der gute Bjarne Stroustrup wohl falsch.



  • @Tankian:

    Hab mal deine Lösung getestet:

    using namespace std;
    class AbstractTerm 
     { 
         public: 
             // ich habs jetzt mal protected gesetzt um die öffentliche 
             // Schnittstelle nicht zuzumüllen. könntest ja dann über nen 
             // globalen friend operator == aufrufen 
             virtual bool equals(const AbstractTerm& other) const 
             {    return other.equals(*this);    } 
    
         // mindestens noch eine rein virtualle Methode, damit die Instanziierung 
         // von AbstractTerm verhindert wird, sonst würde die Methode oben zu ner 
         // Endlosrekursion führen können 
    
         // .. 	
         virtual void prohibit() = 0;
     }; 
    
     class Variable : public AbstractTerm 
     { 
         public: 
             using AbstractTerm::equals; 
    
             virtual bool equals(const Variable& other) const 
             {    return name == other.name;    } 
    				 virtual void prohibit() {}
    
    	 int name;
     }; 
    
    class NotVar : public AbstractTerm {
    	virtual void prohibit() {};	
    };
    
    int main(int argc, char *argv[])
    {
    	Variable V;
    	V.name = 5;
    	NotVar *N = new NotVar;
    	if(!V.equals(*N))  cout << "false" << V.name << endl;
    
      return EXIT_SUCCESS;
    }
    

    Das Programm wird mit SIGSEGV beendet. Musste das Beispiel natürlich etwas umschreiben, damit es compiliert. Habe ich irgendwo einen Fehler, oder stimmt etwas mit der Lösung nicht?



  • Ich habe jetzt mal geschaut wie man das am Best lösen könnte und hab mir mal folgendes ausgedacht. Das Problem ist dass wenn ich das mit VC++.NET 2003 compilere stürzt mir das Programm beim Ausführen mit einem Runtime Error einfach ab weiss leider nicht warum. Hab beim Debuggen (stürtzt beim equals ab) irgendwas von keinem RTTI gelesen obwohl ich in MyBase ja ne Virtuelle gemacht hab. Das arge ist dass die exe die mir MinGW g++ aus der GNU COMPILER COLLECTION erstellt fehlerlos funktioniert.

    Ist das nun ein VC++.NET Bug oder ist mein Code einfach nicht standardkonform?

    #include <iostream>
    #include <memory>
    
    class MyBase
    {
    public:
      MyBase();
      virtual ~MyBase();
    
      friend bool operator ==(MyBase &left,MyBase &right);
    
      virtual bool equals(MyBase &other) =0;
    };
    
    MyBase::MyBase() { }
    MyBase::~MyBase() { }
    
    bool operator ==(MyBase &left, MyBase &right)
    { return left.equals(right);
    }
    
    class MyDerived : public MyBase
    {
    public:
      MyDerived(int key);
      virtual ~MyDerived();
    
      virtual bool equals(MyBase &other);
    
    private:
      int mKey;
    };
    
    MyDerived::MyDerived(int key) : MyBase(), mKey(key) { }
    MyDerived::~MyDerived() { }
    
    bool MyDerived::equals(MyBase &other)
    { const MyDerived *p=dynamic_cast<MyDerived *>(&other);
      return p!=NULL&&mKey==p->mKey;
    }
    
    int main(int argc, char **argv)
    { std::auto_ptr<MyBase> a(new MyDerived(13));
      std::auto_ptr<MyBase> b(new MyDerived(13));
    
      std::cout<<a->equals(*b)<<std::endl;
    
      return 0;
    }
    


  • Hui, mein Code funzt jetzt auch mit VC++.NET Aus irgendwelchen gründen war bei den Compilereinstellungen "Laufzeit-Typeninformationen aktivieren" auf Nein gesetzt. Mit Ja(/GR) gehts nun, bin ich froh.

    Good N(9-1)!



  • hmm...sceint wirklich nicht so ganz zu klappen...



  • Ja, ich hätt genauer nachlesen sollen ..
    So is es jetzt wirklich richtig:

    class Variable;
    
    class AbstractTerm
    {
        protected:
            virtual bool equals(const AbstractTerm&) const = 0;
            virtual bool equals(const Variable&    ) const = 0;
            // für alle weiteren Derived Klassen auch 
            // so eine Methode bereitstellen
    
        friend bool operator ==(const AbstractTerm&, const AbstractTerm&);
    };
    
    class Variable : public AbstractTerm
    {
        protected:
            virtual bool equals(const AbstractTerm& other) const
            {   return other.equals(*this);    }
    
            virtual bool equals(const Variable&     other) const
            {   return name == other.name;     }
    
        // ..
    };
    
    bool operator ==(const AbstractBase& a, const AbstractBase& b)
    {    return a.equals(b);    }
    

    Problem war vorher, dass die Überladung von equals in AbstractTerm nicht
    bekannt war, also wurde sie auch in keiner abgeleiteten Klasse aufgerufen
    -> Endlosrekursion

    So is es jetzt natürlich auch nicht mehr ganz schön, da die AbstractTerm
    Klasse alle abgeleiteten kennen muss ..

    Mehr dazu kannst in Mehr effektiv C++ nachlesen, Item 31.


Anmelden zum Antworten