Serializeable Container
-
naja die frage ist, lässt sich das auch auf komplexere datentypen (in form von klassen) anweden ?
Es geht darum das der inhalt dynamisch ist und es eine art serialisierungsroutine geben muss um alle dynamischen speicher mit zu serialisieren und das objekt auf der anderen seite (des sockets) wieder zu assemblieren.bei statischen sachen würd ja n struct reichen oder n dembläd ... falls sich das mit dem dynamischen inhalt auch mit der STL lösen lässt noch die frage, gibt es ein container template für 1 element ? weil n vektor für 1 element zu erzeugen iss n bissl überflüssig find ich

-
Ein einzelnes Element kannst du direkt per op<< schreiben und per op>> wieder auslesen (sofern du für deine Klasse diese Operatoren ünterstützt). Bei komplexeren Klassenstrukturen würde ich jedem Teilnehmer die Stream-Operatoren mitgeben, die dann wieder auf die Serialisierung der Member zurückgreifen, z.B.:
class CCombi { CObject1 m_ob1; CObject2 m_ob2; public: friend ostream& operator<<(ostream& out,const CCombi& data) { return out<<m_ob1<<" "<<m_ob2; } friend istream& operator>>(istream& in,CCombi& data) { CCombi tmp; in>>tmp.m_ob1>>tmp.m_ob2; if(in)data=tmp; return in; } };Solange du vor dem Einlesen weißt, was du für Objekte zu erwarten hast, klappt das ohne Probleme. Wenn die Zusammenstellung variieren kann (z.B. ein Container kann beliebige Objekttypen enthalten), sollte jedes Element noch eine Typkennung mit ausgeben - und zum Einlesen brauchst du eine Factory.
-
Naja, genau das Implementierst Du im op<< und op>> , der muss sich um diese Details kümmern , die Objekte vernünftig sichern und herstellen.
Wenn der Member op<< und op>> nicht unterstützt, musst Du diesen implementieren. Geht das nicht (z.B. Speicherauszug oder Handle zu einer Resource die angelegt werden muss), darfst Du Dir was einfallen lassen um das entsprechend im op<< und op>> zu Implementieren.
So könntest Du für eine offene Datei z.B. den Dateinamen schreiben und beim einlesen das Objekt für die Datei neu erstellen.
Oder den Speicherblock roh schreiben (mit nem Header davor damit Du weißt wo er anfängt und aufhört in der Datei) und beim einlesen neuen Speicher anfordern und den alten Inhalt einlesen.
-
naja mir schwebt da schon konkret was vor:
die abstrakte Klasse BlockObject besteht aus einem MemoryStream, in dem für jeden wert (wie abstrakt auch immer) immer ein word für die bytelänge und dann der wert selbst abgelegt werden.
Am anfang des streams steht immer die gesamtlänge.Die frage wäre nun wie kann ich alle enthaltenen Member-Objekte(variablen, ptr, usw.) quasi in der deklaration ausfindig machen um sie dann in der Streammethode nach definierten Regeln zu speichern ?
Das Objekt soll quasi ein stream für sich sein in dem sich nur die Memberdaten mit ein wenig overhead befinden.
Immer wenn ToStream() oder DoIOSave() aufgerufen wird, werden alle als objekt vorhandenen daten serialisiert (nach standardvorgaben mittels einer DoIOInt/DiIOWord/....-Methode) und in den stream geschriben werden, der wird dann zurückgegeben.FromStream() oder DoIOLoad() nimmt dann quasi nur den Stream her, und arbeitet die DoIO methoden der reihe nach ab und erhält somit das komplette objekt zurück.
Also nochmal für die kurzleser wie erfass ich sowas wie:
int Var1;
in der deklaration einer klasse die von meiner erbt ohne eine spezielle schreibweise verwenden zu müssen? (also praktisch intern einen eintrag in eine art liste machen, erste variable in stream ist vom typ int)
buyakasha was hab ich mir da nur ausgedacht -.-
mfg
Ceos
-
Dazu mußt du vermutlich genauer differenzieren als nur die Länge - zwei gleich große Typen können intern ganz unterschiedliche Bedeutungen haben (vergleiche int und char[sizeof(int)]). Das bedeutet, du mußt am Anfang des Objekts eher eine Art Typ-Kennung setzen, anhand der du deine Klassen (und eventuell die Build-in Typen und einige STL-Klassen wie std::string) unterscheiden kannst - wenn du den Typ kennst, kannst du auch zuordnen, wo im Stream welcher Member steht.
-
CStoll schrieb:
Dazu mußt du vermutlich genauer differenzieren als nur die Länge - zwei gleich große Typen können intern ganz unterschiedliche Bedeutungen haben (vergleiche int und char[sizeof(int)]). Das bedeutet, du mußt am Anfang des Objekts eher eine Art Typ-Kennung setzen, anhand der du deine Klassen (und eventuell die Build-in Typen und einige STL-Klassen wie std::string) unterscheiden kannst - wenn du den Typ kennst, kannst du auch zuordnen, wo im Stream welcher Member steht.
dazu iss zu bemerken das sich das FromStream auch nur erfolgreich auf ein äquivalent gestreamtes Objekt anwenden lässt, also ist die reihenfolge und art der daten identisch, sofern der server und client in dem system mit derselben version der klasse übersetzt wurden.
problematisch kann es dabei nur bei vielschichtigen template-objekten, wenn die nicht einheitliche serialisierbar sind hab ich natürlich ein problem.das eigentliche Problem was sich hier ergibt iss aber eher das ich noch immer nicht weis wie ich die enthaltenen datentypen die eine erbende klasse beinhaltet erkenne um die entsprechenden DoIO-Methoden ausführen zu können.
Ziel des Spiel ist es eine einfach Containerklasse zu entwickeln von der man erbt ohne dabei auf die serialisierung der einzelnen daten achten zu müssen auf die man dann am ende einfach ObjektXYZ.ToStream() ausführt um sie zu serialisieren.
Die identifikation des serialisierten objektes liesse sich zur not noch über ein CRC verfahren regeln, damit man nicht schrottdaten lädt nur weil der progger zu blöd war die version im client zu aktualisieren ^^
-
vielleicht könnte man das auch mit ein paar geschickten PräCompiler-Anweisungen oder Makros lösen iss mir grad noch eingefallen !?
im eigentlichen geht es mir darum dem benutzer meineer klasse keine speziellen typdefinitionen aufzuzwingen nur weil ich die standard wie "int, short, long, usw." nich rausbekomme ;p
-
das eigentliche Problem was sich hier ergibt iss aber eher das ich noch immer nicht weis wie ich die enthaltenen datentypen die eine erbende klasse beinhaltet erkenne um die entsprechenden DoIO-Methoden ausführen zu können.
Was spricht denn gegen eine Fabrik ?
-
Was spricht denn gegen eine Fabrik ?
Das ich bis jetzt noch nicht weis was das sein soll, btw. im mom keine zeit hab nachzusehen, ich les heut abend nomma drüber ;p
-
Wenn du Zeit hast kannst du vielleicht etwas aus dem Konzept von Boost::Serialization übernehmen oder es gleich verwenden?
-
ich seh schon, hab mich da wohl ein wenig übernommen, thx for anregungen, das landet erstmal im ferienstapel wenn ich mal ernsthaft zeit und langeweile hab ^^
-
Schau dir mal folgenden Link an, vielleicht bringt dich das ein wenig weiter

-
thx 2 u
aber in unserem projekt steckt bereits etwas derartiges drinn(und das wirklich extrem umfangreich), und so wie es aussieht, darf ich mich da hineinwerfen und es ein wenig umschreiben, so verprass ich nichmal freizeit für den mist ^^