delete mit zeiger anderen types?
-
helferlein schrieb:
es geht auch nicht darum, anahnd der größe die typen zu erkennen, es geht
nur darum einen spiecherblock dieser größe zu allokieren und diesen dann
als klasse zu interpretieren.das ist totaler blödsinn und wird nicht funktionieren.
nur mit der Größe kann man keine Objekte erzeugen.
Wer ruft denn die Konstuktoren auf?
Das müsste dann der Benutzer ja selbst mittels placement new machen um sein Objekt in den bereitgestelltnen speicher zu bekommen.Was hindert dich daran, eine vernünftige class-Factory zu bauen, die dir nach übergabe eines Schlüssels (string oder int, oder sontst was) ein entsprechende Objekt erzeugt und nen Basisklassenzeiger zurückgibt
edit:
selbst wenn du keine Konstruktoren definiert hast, wird automaitshc einer erzeugt, da bei polymorphen Klassen mindestens die vtables gefüllt werden müssen.
-
vlad_tepesch schrieb:
das ist totaler blödsinn und wird nicht funktionieren.
nur mit der Größe kann man keine Objekte erzeugen.deswegen frag ich ja wie das anders gemacht werden kann.
factorys sind natürlich möglich, nur sehr aufwändig. wenn ich
jeden typ, int, float, structs (jede verschiedene struct)registrieren müsste,
dann gute nacht. user-defined klassen müssen per factory erzeugt werden, aber
bei PODs sollte das doch zu vermeiden sein?!die bisherige lösung besteht wie bereits gesgt aus einem exteren speicher.
damit kann ich immer dieselbe POD-verwaltungsklasse einsetzen.
-
helferlein schrieb:
aber bei PODs sollte das doch zu vermeiden sein?!
Kommt darauf an, was du dir vorstellst. Wie willst z.B. einen 32bit-integer von einem 32bit-float unterscheiden?
-
überhaupt nicht.
class test { public: float f; int i; }; // ...serialisieren test *t = dynamic_cast<test *>(Deserialise(stream)); // dyn_cast nur als beispielda es klassenfactorys gibt, muss ich nur dafür sorgen, dass die daten am richtigen
platz sind. nach der deserialisierung kann ich die erstellte klasse ganz normal
verwenden.
-
Wie behandelst Du einen std::string?
-
das ganze ist zum scheitern verurteilt.
Wie schon gesagt wurde:
die serialisierung des Speichers eines gesammten Objektes macht keinen Sinn.
Ein mal neu kompilieren mit wenigen Änderungen und du kannst alle alten dateien wegschmeißen.
Ganz zu schweigen von einer Compileränderung.bei deiner Methode die Daten aus dem Stream zu holen: woher weißt du wie groß das objekt ist?
Was machst du mit T, die nicht nur Kompositionen aus Elementardatentypen sind und zB selbst speicher anfordern?
-
vlad_tepesch schrieb:
Ein mal neu kompilieren mit wenigen Änderungen und du kannst alle alten dateien wegschmeißen.
Ganz zu schweigen von einer Compileränderung.natürlich. aber sobald die serialisierung fertig ist, muss sie nicht mehr geändert
werden. der rest kann sich ruhig ändern.die größe wird im stream mitgespeichert.
einen std::string sowie bestimmte typen bekommen eine eigene behandlung.
-
helferlein schrieb:
einen std::string sowie bestimmte typen bekommen eine eigene behandlung.
Und damit auch alle Typen, die einen std::string enthalten oder einen std::vector oder einen Typ mit Pimpl-Idiom. Mhhm. Nun wird auch nachträglich gepimlt.
-
volkard schrieb:
Und damit auch alle Typen, die einen std::string enthalten oder einen std::vector oder einen Typ mit Pimpl-Idiom.
eben nicht.
jedes objekt serialisiert nur seine kinder, und auch nur die, die von einer
gewissen klasse erben. das ganze lässt sich bis auf PODs runterbringen.z.b.
class test : public Streamable { public: test() : integer(this), name(this) // registrieren { integer = 5; name = "hallo"; } StreamablePOD<int> integer; StreamablePOD<std::string> name; // std::string bekommt ne extrawurst (spezialisierung) }; Streamable::RegisterClass(Allocator<test>()); Stream s; test t; t.Serialize(s); test *pt = dynamic_cast<test *>(s.Deserialize()); assert(pt->integer == 5);soweit funtzt es schon. stream rein und klasse raus.
ist darauf spezialisiert, eine komplette klassenhierachie mit all ihren
verweisen, etc... laden zu können.vector, string und die ganzen std::*'s bekommen ne eigene spezialisierung.
-
helferlein schrieb:
StreamablePOD<std::string> name; // std::string bekommt ne extrawurstAh! Da hast Du also geschummelt. Ja, diesen Schummel mag ich.
Der führt mich zuclass test:public SomeBase { public: test() :integer(5) ,name(hallo) { } test(istream& in): SomeBase(in), integer(in), name(in) { } void save(ofstream& out) { SomeBase::save(out); integer.save(out); name.save(out); } private: StreamablePOD<int> integer; StreamablePOD<std::string> name; }; REGISTERSTREAMABLE(test,SomeBase);Der Leser macht dann
while(in>>name) ziel.push_back(macher[name].machEinen(in));Der Schreiber macht
for each i in quelle datei<<i->getName()<<' '; i->save(datei);oder so.
-
volkard schrieb:
Ah! Da hast Du also geschummelt. Ja, diesen Schummel mag ich.

es wird sogar noch lustiger:
da jede POD-klasse innerhalb der oberklasse ist, muss ich nur "save"
für die oberste klasse aufrufen. der rest geht automatisch
(innerhalb heißt. this < POD < this + 1)