Десериализация иерархии конструктора

(Этот вопрос очень похож наэтот, но на этот раз я звонюParent десериализационный конструктор вChild список инициализации).

В случае, когдаChild не добавляет новых данных для сериализации,Parent не имеет конструктора по умолчанию, я хочу иметь возможность сериализацииParent объект непосредственно, а такжеChildи ни у потомка, ни у родителя нет конструкторов по умолчанию, кажется, что мы должны использовать следующий шаблон, где дочерний конструктор десериализации инициализирует родителя (также используя его конструктор десериализации) в списке инициализации:

#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;
}

Таким образом, цепочка вызовов должна (и действительно) выглядеть следующим образом:

Выход:

Ребенок :: сериализации ()Родитель :: сериализации ()

Входные данные:

Ребенок (архив)Родитель (архив)Родитель :: сериализации ()

Тем не менееmParentData заканчивается как0 вchildReadкогда я ожидал, что это будет1.2.

Кто-нибудь может определить ошибку?

----------- РЕДАКТИРОВАТЬ -----------

Как указывает @stijn, в случае, когда у ребенка нет дополнительных данных для сериализации, мы можем просто удалитьserialize() функция отChild целиком вот так:

#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;
}

Однако в случае, когда и у дочернего, и у родительского элемента есть данные для сериализации, и у них обоих нет конструктора по умолчанию, шаблон выглядит так, как будто он должен быть чем-то вроде следующего, но не совсем. вChild десериализационный конструктор, мы называем обаParent конструктор десериализации, но такжеChild::serialize() функция, которая вызываетParent::serialize() функция, так эффективноParent попытался бы десериализоваться дважды. Это неправильное поведение демонстрируется здесь:

#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;
}

Кажется, как-то нам нужно назвать другую версиюChild::serialize() отChild десериализационный конструктор? Или установите флаг, чтобы явно не десериализоватьParent отChild::serialize() если он вызывается изChild десериализационный конструктор?

Если мы изменимChild::serialize() к следующему, я получаю 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;
}

Ответы на вопрос(1)

Ваш ответ на вопрос