Deserialisierung der Konstruktorhierarchie

(Diese Frage ist sehr ähnlich zudiese, aber diesmal rufe ich dieParent Konstruktor deserialisieren imChild Initialisierungsliste).

In einem Fall, in dem einChild fügt keine neuen zu serialisierenden Daten hinzu,Parent hat keinen Standardkonstruktor, ich möchte das @ serialisieren könnParent Objekt direkt sowie dasChild, und weder das untergeordnete noch das übergeordnete Element haben Standardkonstruktoren. Anscheinend sollten wir das folgende Muster verwenden, bei dem der untergeordnete Deserialisierungskonstruktor das übergeordnete Element (auch mit seinem Deserialisierungskonstruktor) in der Initialisierungsliste initialisiert:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <fstream>

class Parent
{
public:
    double mParentData;

    Parent(const double data) : mParentData(data) {}

    template<typename TArchive>
    Parent(TArchive& archive)
    {
        archive >> *this;
    }

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    {
        archive & mParentData;
    }
};

class Child : public Parent
{
public:

    Child(const double data) : Parent(data) {}

    template<typename TArchive>
    Child(TArchive& archive) : Parent(archive)
    {
        // Do nothing, as the only data to read is in Parent
    }

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    {
        // Let the parent do its serialization
        archive & boost::serialization::base_object<Parent>(*this);

        // Nothing else to do, as the only data to read/write is in Parent
    }
};

int main()
{
    Child child(1.2);

    {
        std::ofstream outputStream("test.txt");
        boost::archive::text_oarchive outputArchive(outputStream);

        outputArchive << child;
        outputStream.close();
    }

    {
        std::ifstream inputStream("test.txt");
        boost::archive::text_iarchive inputArchive(inputStream);
        Child childRead(inputArchive);

        std::cout << "childRead:" << std::endl
                  << childRead.mParentData << std::endl; // Outputs 0 (expected 1.2)
    }

    return 0;
}

So sollte die Aufrufkette aussehen (und sieht auch so aus):

Ausgabe

Child :: serialize ()Parent :: serialize ()

Eingang

Child (Archiv)Parent (Archiv)Parent :: serialize ()

DermParentData endet als0 imchildRead, wenn ich es erwarten würde1.2.

Kann jemand den Fehler erkennen?

----------- EDIT -----------

Wie von @stijn erwähnt, können wir in dem Fall, in dem das Kind keine zusätzlichen Daten zum Serialisieren hat, einfach das @ entferneserialize() Funktion vonChild ganz so:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <fstream>

class Parent
{
public:
    double mParentData;

    Parent(const double data) : mParentData(data) {}

    template<typename TArchive>
    Parent(TArchive& archive)
    {
        archive >> *this;
    }

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    {
        archive & mParentData;
    }
};

class Child : public Parent
{
public:

    Child(const double data) : Parent(data) {}

    template<typename TArchive>
    Child(TArchive& archive) : Parent(archive)
    {
        // Do nothing, as the only data to read is in Parent
    }

};

int main()
{
    Child child(1.2);

    {
        std::ofstream outputStream("test.txt");
        boost::archive::text_oarchive outputArchive(outputStream);

        outputArchive << child;
        outputStream.close();
    }

    {
        std::ifstream inputStream("test.txt");
        boost::archive::text_iarchive inputArchive(inputStream);
        Child childRead(inputArchive);

        std::cout << "childRead:" << std::endl
                  << childRead.mParentData << std::endl; // Outputs 0 (expected 1.2)
    }

    return 0;
}

In dem Fall, in dem sowohl das untergeordnete als auch das übergeordnete Element zu serialisierende Daten haben und beide keinen Standardkonstruktor haben, muss das Muster wie folgt aussehen, aber nicht ganz. In demChild deserializing Konstruktor, rufen wir beide dieParent deserialisierender Konstruktor, aber auch dasChild::serialize() -Funktion, die das @ aufruParent::serialize() Funktion, so effektiv dieParent würde versuchen, zweimal zu deserialisieren. Dieses falsche Verhalten wird hier demonstriert:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <fstream>

class Parent
{
public:
    double mParentData;

    Parent(const double data) : mParentData(data) {}

    template<typename TArchive>
    Parent(TArchive& archive)
    {
        archive >> *this;
    }

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    {
        archive & mParentData;
    }
};

class Child : public Parent
{
public:

    double mChildData;

    Child(const double parentData, const double childData) : Parent(parentData), mChildData(childData) {}

    template<typename TArchive>
    Child(TArchive& archive) : Parent(archive)
    {
        archive >> *this;
    }

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    {
        // Let the parent do its serialization
        archive & boost::serialization::base_object<Parent>(*this);

        // Do the child serialization
        archive & mChildData;
    }
};

int main()
{
    Child child(1.2, 3.4);

    {
        std::ofstream outputStream("test.txt");
        boost::archive::text_oarchive outputArchive(outputStream);

        outputArchive << child;
        outputStream.close();
    }

    {
        std::ifstream inputStream("test.txt");
        boost::archive::text_iarchive inputArchive(inputStream);
        Child childRead(inputArchive);

        std::cout << "childRead:" << std::endl
                  << childRead.mParentData << std::endl  // Outputs 0.2 (expected 1.2)
                  << childRead.mChildData << std::endl; // Outputs 3.4 correctly
    }

    return 0;
}

Es scheint, als müssten wir irgendwie eine andere Version von @ aufrufChild::serialize() von demChild Konstruktor deserialisieren? Oder setzen Sie ein Flag, um @ nicht explizit zu deserialisiereParent vonChild::serialize() wenn es vom @ aufgerufen wiChild Konstruktor deserialisieren?

Wenn wir das @ ändeChild::serialize() zu folgendem bekomme ich einen segfault:

template<class TArchive>
void serialize(TArchive& archive, const unsigned int version)
{
    // Let the parent do its serialization
    Parent::serialize(archive, version);

    // Do the child serialization
    archive & mChildData;
}

Antworten auf die Frage(2)

Ihre Antwort auf die Frage