Container für verschiedene Objekte
-
Michael E. schrieb:
BTW: Den tatsächlichen Typ findest du mit typeof() raus.
Ne, typeof ist ne Erweiterung, die einige Compiler anbieten. Sie wertet zur Compilezeit den Typ eines Ausdrucks aus.
-
Dafür gibt es Vererbung, damit man eben genau das nicht wissen muss:
class Base { virtual string Name() =0; }; class Derived1 : public Base { string Name() { return "Derived1"; } }; class Derived2 : public Base { string Name() { return "Derived2"; } }; int main() { vector<Base*> v; v.push(new Derived1()); v.push(new Derived2()); for(int i=0; i<v.size(); ++i) cout << v[i]->Name() << endl; }Du solltest dir dazu mal ein Buch über OOP durchlesen oder zumindest ein gutes Tutorial, wo das Prinzip der Vererbung und Polymorphie erklärt wird.
Wenn die Klassen wie, hier oben erwähnt, nicht alle Funktionen gemeinsam haben, musst du casten oder solltest deine Logik nochmal überdenken.
-
Vellas schrieb:
vector<Base*> v; v.push(new Derived1()); v.push(new Derived2()); for(int i=0; i<v.size(); ++i) cout << v[i]->Name() << endl; }Oh, ich wusste nicht, dass ich in einen Vektor der Basisklasse auch die abgeleiteten Klassen reinpacken kann.
Könnte ich dann prinzipiell eine (fast) leere Klasse machen von der dann alle anderen Klassen erben, nur um diese funktionalität dann zu haben?Vielen Dank!
R
-
std::Robin schrieb:
Könnte ich dann prinzipiell eine (fast) leere Klasse machen von der dann alle anderen Klassen erben, nur um diese funktionalität dann zu haben?
Könntest du, ist aber, wie mehrere Vorredner bereits gesagt haben, vom Designstandpunkt her Blödsinn. Wenn du dann nämlich jedes Objekt erst nach seinem tatsächlichen Typ fragen musst, bevor du irgendetwas damit machst, hast du noch nicht verstanden, wozu man Vererbung einsetzt.
-
Oh, ich wusste nicht, dass ich in einen Vektor der Basisklasse auch die abgeleiteten Klassen reinpacken kann.
Neee kannst du eben nicht ... die container sind typegebunden.
du packst da keine Instanzen unterschiedlicher klassen rein, sondern zeiger auf diverse instanzen ....
Wenn die abgeleitet sind, isses ok, geht aber auch ganz ohne (void * container) ^^ wenn man beim zurueckcasten weiss was man tut. ^^Die schoenste form unterschiedliche Typen in nem container zu halten, ist ueber nen gemiensamen Adapter.
Also ne classe vom Typ Gepaeckstuck, der du besipielsweisse nen anderen Typ ... Socke zum beispiel, occupieren(uebernehmen) kannst. Dein koffer hausst dann nur mit "gepaeckstuecken" voll ... Das ist aber ziemlich aufwendig und lohnt sich nur in wenigen faellen ...Ciao ...
-
class item { public: unsigned int weight; unsigned int width; unsigned int length; unsigned int height; virtual unsigned short gettype()=0; item(){} };class weapon : public item { public: unsigned short aua; unsigned long owner_id; std::string name; unsigned short gettype(); weapon(); };class armor : public item { public: unsigned long schutz; unsigned long owner_id; std::string name; unsigned short gettype(); armor(); };Also ganz konkret. Ich möchte Waffen und Schutzkleidung in einen Koffer packen, der aber nur ein gewisses Limit an Gewicht und/oder Volumen aufnehmen kann.
Dafür hab ich die Klassen oben erstellt. Jetzt hakt es am Koffer selber - da sollen nur Objekte vom Typ Armor und Weapon rein, später noch mehr...
Bisher hatte ich zwei Ansätze versucht: Metaobjekte, also Kapselung und 2 Vektoren (für jede Klasse einen), was mir aber zu umständlich wird wenn ich da noch mehrere Sachen reinpacken möchte.Ich dachte es wäre möglich ein enum von möglichen Objekten zu machen, und dann einen Vektor über das enum zu machen, klappt aber auch nicht. Das mit den Vektor über Zeigern klappt nicht, weil ich irgendwie nachher nicht mehr dereferenzieren kann.
Ich würde später deann auch gerne Methoden für den Koffer programmieren, wie z.B. entnehme_objekt_nummer(fortlaufende nummer), lege_waffe_in_den_koffer(&armor) <- push_back()....
Hat jemand eine Idee wie man so einen Koffer einfach und effizient verwirklichen kann?
Gruss
R
-
Hallo nochmal,
ich denke, ich habe es hinbekommen:
vector<item*> v; v.push_back(new weapon()); v.push_back(new armor()); cout<<v[0]->gettype(); cout<<v[1]->gettype(); if (v[0]->gettype() ==1) //wenn 1 dann ists ne waffe { weapon *a; a=(weapon*) v[0]; cout <<endl<<"jjjjjjjjj:"<<a->name<<endl; };Das mag vielelicht alles andere als optimal sein, aber für mich als Anfänger langts allemal.
Vielen Dank an alle.
Gruss
R
-
Und das Freigeben des Speichers durch delete solltest nicht vergessen:
vector<Base*> v; // wird hier mit irgendwas befüllt // speicher freigeben und zeiger löschen: while(v.size()) { delete v.back(); v.pop_back(); }
-
Ein einzelnes Element aus der Mitte löschen geht also mit
delete v.begin() + pos; v.erase (v.begin() + pos);richtig?
Gruss
R
-
wenn du oft elemente aus der mitte löschen willst, dann nimm lieber std::list.
-
Schau dier aus der Boost Bibliothek die any-Klasse an.
Thomas
-
Btw, da offenbar alle deine Items einen Namen haben, solltest du die "string name;" auch mit in die Basisklasse auslagern.