operator = in abgeleiteter Klasse
-
Welche Veriante würdet ihr bevorzugen?
bool Variable::operator ==(const AbstractTerm &other) const { try { Variable &p=dynamic_cast<Variable &>other; if(mName==p.mName) { return true; } else { return false; } } catch(const bad_cast &exception) { return false; } } bool Variable::operator ==(const AbstractTerm &other) const { Variable *p=dynamic_cast<Varaible *>&other; if(p!=NULL) { if(mName==p->mName) { return true; } else { return false; } } else { return false; } }
-
beide evrsionen sind häßlich^^
wie wärs damit:
bool Variable::operator ==(const AbstractTerm& other) const{ return false; } bool Variable::operator ==(const Variable& other) const{ return mName==other.mName; }
selbstoptimierender code ohne dynamic_cast
//edit arrgh nichma copy pasten kann man, ohne dass die variablen namen kaputt gehen^^
-
danke otze, mir taten schon die Augen weh.
tooler:
Nichts für ungut. ^^
-
Ich hab dann später aber nur noch Pointer auf die Basisklasse in einr Kollection. Wird dass dann automatisch erkannt dass ein AbstractTerm * auf eine Variable zeigt???
-
Zudem wäre es vorteilhaft, den Operator global zu definieren.
-
tooler schrieb:
Ich hab dann später aber nur noch Pointer auf die Basisklasse in einr Kollection. Wird dass dann automatisch erkannt dass ein AbstractTerm * auf eine Variable zeigt???
sorry, musste das kurz testen
nein, es wird nicht automatisch konvertiert
-
Also ist die ursprüngliche frage immer noch nisch geklärt!!
-
solange du da oben im beispiel mit referenzen arbeitest schon^^
-
The C++ Programming Language:
14.11 Advice:
Use exeptions for error handling;
Don't use exeptions when more local control structures will suffice;
-
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)
-
Na, in diesem Fall lag dann der gute Bjarne Stroustrup wohl falsch.
-
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...