(这个问题和this one非常相似,但是这次我调用了Child
初始化列表中的Parent
反序列化构造函数)。
在 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 ::序列化()
- 父级::序列化()
输入:
- child (存档)
- parent (存档)
- 父级::序列化()
但是,mParentData
在 childRead
中最终为 0
,而我希望它是 1.2
.
谁能发现错误?
------------ 编辑------------
正如@stijn 所指出的,在 child 没有额外数据要序列化的情况下,我们可以简单地从 Child
中完全删除 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
反序列化构造函数调用的,则不从 Child::serialize()
显式反序列化 Parent
?
如果我们将 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++ - 反序列化构造函数层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36222439/