konkrete Objekte abstrakter Klassen Clonen
-
Hi Leute,
am folgendem Problem tüftle ich momentan:
Ich habe eine Klassenhierarchie, mit im Endeffekt, zwei "Parteien",
den "Agenten" die über ihre "Umwelt" etwas wissen und mit ihr Interagieren können,
und den "ControlAgenten", die "Agenten" kennen und diese "Steuern".
Unter Bestimmten Umständen muss der "ControlAgent" allerdings, einen seiner "Agenten", Clonen ( z.B. aufgrund von Agenten mangel ;-).
Und hier ist mein Problem, wie stell ich das an?
Dadurch dass ich nur einen Zeiger auf eine abstrakte Klasse habe, fehlt mir ja die Information um welche konkrete Klasse es sich handelt.
Zusätzlich kenne ich ja den spezifischen Konstruktor nicht...
Nun suche ich hierzu eine elegante Möglichkeit das zu bewerkstelligen.Meine Ideen waren folgende:
1. Der "ControlAgent" nimmt nicht einen konkreten "Agenten" auf, sondern nur ein "FactoryObjekt" , welches einen konkreten Agenten instanzieren kann.
2. Irgendwie den Speicher mit memcpy Kopieren( und danach seinen zustand mit ResetState() inizieren )
Aber am liebsten wäre mir doch wenn jeder Agent eine Funktion "Create" hätte, um eine neue Instanz seiner selbst zu erstellen(am besten genauso wie er selbst erstellt wurde).
class AbstractAgent { //.... public: virtual void ResetState()=0; virtual Message DoIt( Data const& )=0; }; class AbstractControlAgent : public AbstractAgent { std::vector<AbstractAgent*> Agents; public: int/*ID*/ AddAgent( AbstractAgent*)//Fügt einen Agenten hinzu //... }; class ControlAgent1 : public AbstractControlAgent { public: virtual Message DoIt( Data const& ) { // Let Agents Do Sth. } }; class Agent1 : public AbstractAgent { private: int Counter; public: Agent1(int Counter): AbstractAgent(...), Counter(Counter) {} virtual void ResetState(){....} virtual Message DoIt( Data const& ); }; class Agent2 : public AbstractSlave { private: std::string Text; public: Agent2(std::string Text): AbstractAgent(...), Test(Test) {} virtual void ResetState(){....} virtual Message DoIt( Data const& ); };gruss
AgentX
-
Naja, du sagst es doch schon, lass die Klassen sich selbst klonen!
-
Decimad schrieb:
Naja, du sagst es doch schon, lass die Klassen sich selbst klonen!
Ja und hier weis ich nicht genau wie ich das machen könnte:
- Füre ich nun eine virtuell/abstrakte methode ein, die dann in Jeder Konkreten Klasse definiert wird.
- Oder kopiere ich einfach mit Memcpy den gesamten Speicher ( die größe des benötigten Speichers könnte man mit ner template klasse ermitteln und von dieser erben lassen (Currious recurring Patter?) )Und was sollte der Rückgabewert dieser Funktion Sein?
Die konkrete Klasse? ( und einen Kopierkonstruktor zu definieren? )
Aber wie speichere ich dann dieses Objekt wenn das innerhalb einer Funktion geschieht und dieses auch danach bestehen soll.
Ich meine wenn ich dieses Objekt in den Vector pusche und ich den Gültigkeitsbereich verlasse, wird da nicht das Objekt zerstört?oder ein Zeiger auf die Basisklasse?
Oder Sollte ich beide Anbieten?
-
Ersteres.
Der Memcpy-Weg schlägt bei allen Fällen fehl, in denen die Objekte Referenzen oder Handles oder was auch immer auf etwas externes enthalten.Ja, sagen wir, du hast folgendes:
class AgentBase { public: virtual AgentBase* Clone() = 0; }; class AgentA : public AgentBase { AgentBase* Clone() { return new AgentA(*this); // Oder wie auch immer du das kopieren des Zustands umsetzen magst } };
-
Du darfst in der Implementiertung von Clone() sogar AgentA* als Rückgabetyp angeben (covariant return types).
-
Wie ist das eigentlich, wenn das Objekt im Vector ist, kümmert sich der vector eigentlich über die speicherfreigabe wenn dieser Zerstört wird?
-
AgentX schrieb:
Wie ist das eigentlich, wenn das Objekt im Vector ist, kümmert sich der vector eigentlich über die speicherfreigabe wenn dieser Zerstört wird?
Kommt darauf was Du unter "wenn das Objekt im Vector ist" verstehst.
Wenn Du darunter verstehst, dass im Vector Pointer sind, welche auf ein mit new angelegtes Objekt zeigen - dann nicht.Wenn tatsächlich Objekte im Vector sind, dann schon.
Simon
-
AgentX schrieb:
Wie ist das eigentlich, wenn das Objekt im Vector ist, kümmert sich der vector eigentlich über die speicherfreigabe wenn dieser Zerstört wird?
Ja, aber nur um die Objekte selber. Wenn die Objekte Zeiger sind, wird der Speicher dahinter nicht automatisch freigegeben. Deshalb sollte man auch vorsichtig sein mit besitzenden Zeigern in STL-Containern.
Eine Alternative ist die Bibliothek Boost.PointerContainer.
-
Oder ein container<unique_ptr<T>>