delete mit zeiger anderen types?



  • natürlich. wenn man den compiler wechselt kann alles schief gehen, was
    ein gewisses memory-layout erfordert.

    serialisation ist generell nicht einfach, ich versuche erstmal eine variante
    (binär) zum laufen zu bekommen. später wird das ganze um eine textversion
    (wird wohl XML werden) erweitert.

    PODs würden vllt funktionieren, jedoch die ganze schöne objektorientierung
    inkl. polymorphie kaputtmachen.

    habs erstmal mit externen verweisen auf PODs gelöst, hoffe das wird noch 🙂



  • 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.


  • Mod

    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 beispiel
    

    da 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 extrawurst
    

    Ah! Da hast Du also geschummelt. Ja, diesen Schummel mag ich.
    Der führt mich zu

    class 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)


Anmelden zum Antworten