其他分享
首页 > 其他分享> > c-反序列化构造函数层次结构

c-反序列化构造函数层次结构

作者:互联网

(此问题与this one非常相似,但是这次我在Child初始化列表中调用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:

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

因此,调用链应该(并且确实)看起来像:

输出:

> Child :: serialize()
>父母:: serialize()

输入:

>儿童(档案)
>父母(档案)
>父母:: serialize()

但是,当我希望mParentData为1.2时,它在childRead中最终为0.

谁能发现错误?

———–编辑———–

如@stijn所指出的,在子级没有其他要序列化的数据的情况下,我们可以简单地从子级中完全删除serialize()函数,如下所示:

#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反序列化构造函数中调用不同版本的Child :: serialize()?还是设置一个标志,以防止从Child :: serialize()中显式地反序列化Parent:如果从Child反序列化构造函数中调用了它?

如果将Child :: serialize()更改为以下内容,则会出现段错误:

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

解决方法:

我相信您不需要将反序列化转发给父级.
将代码更改为

#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, bool deserialize = false)
  {
    if (!deserialize)
      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, true)
  {
    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);

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

为我工作.

标签:c,serialization,boost,boost-serialization
来源: https://codeday.me/bug/20191012/1901425.html