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

时间:2016-03-25 15:02:00

标签: c++ serialization boost boost-serialization

(这个问题与this one非常相似,但这次我在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;
}

所以调用链应该(并且确实)看起来像:

输出:

  • Child :: serialize()
  • 父::的serialize()

输入:

  • 子(存档)
  • 父(存档)
  • 父::的serialize()

但是,mParentData 0中的childRead最终为1.2,我希望它为serialize()

有人能发现错误吗?

-----------编辑-----------

正如@stijn所指出的,如果孩子没有其他数据要序列化,我们可以完全从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()明确反序列化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; }

如果我们将Converter更改为以下内容,则会出现段错误:

itemValue

1 个答案:

答案 0 :(得分:0)

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

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

适合我。