3 == -858993460?
-
Ich habe folgende Klasse geschrieben:
template <class T> class DLL Warrior : public T { private: Warrior& operator++(){lvlup();return *this;} protected: int dmgg, dmga, dmg, HP, HP_max, armor, freq, see, fast, radius, mana; bool flying; int give_exp, needed_exp, now_exp, level; public: Warrior(){Init();} virtual ~Warrior(){} inline void setdmga(int ndmga); inline void setdmgg(int ndmgg); inline void setdmg(int ndmg); inline void setHP(int nHP); inline void setHP_max(int nHP_max); inline void setmana(int nmana); inline void setarmor(int narmor); inline void setfast(int nfast); inline void setsee(int nsee); inline void setfreq(int nfreq); inline void setradius(int nradius); inline void setflying(bool nflying); inline void setgive_exp(int ngive_exp); inline void setnow_exp(int nnow_exp); inline void setneeded_exp(int nneeded_exp); inline void setlevel(int nlevel); inline int getdmga() const {return(dmga);} inline int getdmgg() const {return(dmgg);} inline int getdmg() const {return(dmg);} inline int getHP() const {return(HP);} inline int getHP_max() const {return(HP_max);} inline int getmana() const {return(mana);} inline int getarmor() const {return(armor);} inline int getfast() const {return(fast);} inline int getsee() const {return(see);} inline int getfreq() const {return(freq);} inline int getradius() const {return(radius);} inline bool getflying() const {return(flying);} inline int getgive_exp() const {return(give_exp);} inline int getnow_exp() const {return(now_exp);} inline int getneeded_exp() const {return(needed_exp);} inline int getlevel() const {return(level);} virtual bool levelup(); };
Als Policy-Oberklasse:
class DLL Warrior_Policy { public: virtual bool lvlup(){return false;} virtual void Init(){} };
Als Policy:
class Arbeiterstr : public Warrior_Policy { private: int dmgg, dmga, dmg, HP, HP_max, armor, freq, see, fast, radius, mana; bool flying; int give_exp, needed_exp, now_exp, level; public: virtual void Init(); virtual bool lvlup(); }; void Arbeiterstr::Init() { dmgg = 3 ; dmga = 0 ; dmg = 3 ; HP = 30 ; HP_max = 30 ; armor = 1 ; freq = 60 ; see = 5 ; fast = 5 ; radius = 1 ; mana = 0 ; now_exp = 0 ; give_exp = 10 ; needed_exp = 20 ; level = 0 ; flying = false; } bool Arbeiterstr::lvlup() { if(now_exp > needed_exp) { ++dmgg; ++dmg; ++fast; return true; } return false; } typedef Warrior<Arbeiterstr> Arbeiter;
Dann habe ich folgendes geschrieben:
int main() { Arbeiter Hase; cout << Hase.getdmga() << endl; cout << Hase.getdmgg() << endl; cout << Hase.getdmg() << endl; cout << Hase.getHP() << endl; cout << Hase.getHP_max() << endl; cout << Hase.getmana() << endl; return 0; }
Es kam zwar kein Fehler, aber mir wurde 6 mal die Zahl -858993460 ausgegeben.
Wie kann das sein? Ich habe ausdrücklich Werte zugewiesen die nicht 858993460 entsprrachen und über das Int-Maximum bin ich ja wohl auch kaum gekommen.
Was mache ich falsch?
mfg
Glamdring
-
Du rufst init nicht auf ? (nur kurz überflogen)
-
Knuddlbaer schrieb:
Du rufst init nicht auf ? (nur kurz überflogen)
Steht im ctor
-
doppelpost
-
doppelpost
-
Gut, dass hier einer so gut zählen kann
-
Das Problem ist, es wird das Init() aus der Basisklasse aufgerufen weil zum Zeitpunkt des Basisklassen-Konstruktors die abgeleitete noch nicht existiert.
Du musst Init() im Konstruktor der Abgeleiteten aufrufen.
-
Interessant, muss ich dann also
tempplate <> Warrior<Arbeiterstr>::Warrior() { Init(); }
schreiben, oder wie?
mfg
Glamdring
-
Nö, hab nur zu schnell gelesen.
Setz den Debuger doch mal in die Init und schau was da pssiert
-
Wenn ich nichts falsch sehe, hast du dmga usw. einmal in Arbeiterstr und einmal in Warrior definiert. Der Wert, den Arbeiterstr::Init ändert, ist also ein anderer, als der, den get_dmga zurückgibt.
Das Design sieht irgendwie seltsam aus. Warum eine Policy? Warum leitet Arbeiter nicht von Warrior ab? Das wäre IMHO sinnvoller. Wenn du die Variablen in Arbeiterstr löschst, hast du das Problem, das DrGreenthumb erwähnt hat - die Basisklasse weiß natürlich nichts über die Elemente der abgeleiteten Klassen. Außerdem bringt virtual so natürlich nicht viel, weil du für die verschiedenen Einheiten keine gemeinsame Basisklasse hast, jedenfalls keine sehr hilfreiche.
IMHO wäre Warrior hier besser eine Basisklasse (sieht ja auch wie eine aus) und die übergeordneten Konstruktoren können dann im Konstruktor (wozu Init()?) die Werte ändern.BTW: Ist es Absicht, dass du einmal lvlup und einmal levelup hast?
-
1. dmga usw. sind in Arbeiterstr private und daher in Warrior<Arbeiter> nicht mehr vorhanden folglich können nur die dmga... geändert werden, die auch existieren.
2. Ja lvlup() wird von Arbeiterstr mitgebracht und wird in levelup() aufgerufen.
3. Das mit dem Design kommt ja immer auf den Kontext an, Warrior ist nur deshalb auch als Superklasse nutzbar, damit der Code erweiterbar bleibt, bzw es zusätzliche, auf Warrior aufbauende Implementierungen geben soll.mfg
Glamdring
-
1. Wenn ich da nicht wirklich viel übersehe: dmga usw. sind ja nicht "nicht mehr vorhanden", sondern einfach nur private. Arbeiterstr::Arbeiterstr() kann Arbeiterstr::dmga natürlich trotzdem verändern. Arbeiter::get_dmga() gibt aber Warrior<Arbeiterstr>::dmga aus. Eine schöne Lösung dafür sehe ich nicht, deshalb finde ich das Design komisch.
-
Soweit ich wusste, werden private-member überhaupt nicht weitervererbt, sonst wäre ja protected total nutzlos.
mfg
Glamdring
-
Man kann nur in der eigenen Klasse darauf zugreifen, existieren müssen sie trotzdem. Wie soll sonst folgender Code funktionieren:
class Base { int basePriv; public: Base() : basePriv(1337) {} int accessor() const { return basePriv; } }; class Derived : public Base { public: void ausgabe() const { std::cout << accessor() << std::endl; } };
Genau so sieht die Situation bei dir aus, nur dass du in Derived nochmal eine Variable des gleichen Namens hast. Das ändert natürlich nichts an der Basisklasse, denn einmal geschriebene Klassen kann man in C++ auf keine Weise mehr verändern (mal von der Spezialisierung von template-Elementfunktionen abgesehen).
-
Also ist protected völlig nutzlos, oder verstehe ich das wieder nicht?
-
OK, jetzt hab ichs verstanden(protected) und auch eine Lösung gefunden:
Ich verschiebe alle Variablen aus Arbeiterstr nach protected und lösche alle Variablen aus Warrior. Mein Compiler compiliert es jedenfalls.mfg
Glamdring
-
Dann muss es aber this->dmga usw. heißen, damit es legal ist. Sonst kann der Compiler eigentlich nicht wissen, woher dmga kommt.