使用Boost:serialize反序列化指向派生类的指针时出现问题
Problems deserializing a pointer to a derived class using Boost:serialize
我在尝试使用boost serialize反序列化指向派生类的指针时遇到了一个奇怪的问题。我有一个基础,并在其外部派生了保存/加载函数(非侵入式版本),但每次我尝试反序列化指针时,我都会遇到"输入流错误"异常或"未注册类"异常。我是这样做的:
首先我定义了我的类:
#include <fstream>
#include <iomanip>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/archive_exception.hpp>
#include "boost/serialization/split_free.hpp"
#include "boost/serialization/export.hpp"
#include "boost/serialization/utility.hpp"
#include <boost/serialization/string.hpp>
#include <boost/serialization/binary_object.hpp>
class Base
{
public:
bool isEnabled;
Base();
virtual ~Base(){}
};
Base::Base()
{
isEnabled = 0;
}
class Derived : public Base
{
public:
Derived();
virtual ~Derived(){}
int layerHeight;
};
Derived::Derived():Base()
{}
然后我确定他们的特征是我需要的:
BOOST_CLASS_EXPORT_GUID(Base, "Base")
BOOST_SERIALIZATION_SPLIT_FREE(Base)
BOOST_CLASS_IS_WRAPPER(Base)
BOOST_CLASS_TRACKING(Base, boost::serialization::track_selectively)
BOOST_CLASS_IMPLEMENTATION(Base, boost::serialization::object_class_info)
BOOST_SERIALIZATION_SPLIT_FREE(Derived)
BOOST_CLASS_EXPORT_GUID(Derived, "Derived")
BOOST_CLASS_IS_WRAPPER(Derived)
BOOST_CLASS_IMPLEMENTATION(Derived, boost::serialization::object_class_info)
BOOST_CLASS_TRACKING(Derived, boost::serialization::track_selectively)
接下来我定义实际的保存/加载功能:
namespace boost {
namespace serialization {
template<class Archive>
void save(Archive & ar,const Base& obj, const unsigned int version)
{
bool isEnabled = obj.isEnabled;
ar << BOOST_SERIALIZATION_NVP(isEnabled);
}
template<class Archive>
void load(Archive & ar, Base& obj, const unsigned int version)
{
bool isEnabled;
ar >> BOOST_SERIALIZATION_NVP(isEnabled);
}
} // namespace serialization
} // namespace boost
namespace boost {
template<>
struct is_virtual_base_of<Base, Derived>: public mpl::true_ {};
namespace serialization {
template<class Archive>
void save(Archive & ar,const Derived& obj, const unsigned int version)
{
ar & boost::serialization::base_object<Base>(obj);
int height =obj.layerHeight;
ar << BOOST_SERIALIZATION_NVP(height);
}
template<class Archive>
void load(Archive & ar, Derived& obj, const unsigned int version)
{
ar.template register_type<Base>();
ar.template register_type<Derived>();
ar & boost::serialization::base_object<Base>(obj);
int height;
ar >> BOOST_SERIALIZATION_NVP(height);
}
} // namespace serialization
} // namespace boost
还有我从Docs 借来的2个保存/加载助手
template <typename T>
void save_schedule(const T& s, const char * filename){
// make an archive
std::ofstream ofs(filename);
assert(ofs.good());
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(s);
}
template <typename T>
void restore_schedule(T &s, const char * filename)
{
// open the archive
std::ifstream ifs(filename);
assert(ifs.good());
boost::archive::xml_iarchive ia(ifs);
// restore the schedule from the archive
ia >> BOOST_SERIALIZATION_NVP(s);
}
最后-这里是我如何尝试使用它所有
int main(int argc, char *argv[])
{
Base* basePointer = new Base();
Base* objectPointer = new Derived();
Derived * secondObjectPointer = new Derived();
Derived justObject;
save_schedule(basePointer, "C:\basePointer.xml");
save_schedule(objectPointer, "C:\objectPointer.xml");
save_schedule(secondObjectPointer , "C:\secondObjectPointer.xml");
save_schedule(justObject, "C:\justObject.xml");
//this works OK
restore_schedule(basePointer, "C:\basePointer.xml");
//this gives "Input Stream Error"
restore_schedule(objectPointer, "C:\objectPointer.xml");
//this gives "Unregistered class"
restore_schedule(secondObjectPointer, "C:\secondObjectPointer.xml");
//This works >__< But I need to serialize pointers so I cannot use this
restore_schedule(justObject, "C:\justObject.xml");
}
我做错了什么?为什么除了指向基类的指针之外,我不能反序列化其他任何东西?
UPD::经过更多的搜索,我能够将我的问题追踪到以下答案:
boost序列化异常:未注册类,序列化多态基问题
更换
//original taken from Boost Docs
ar & boost::serialization::base_object<Base>(obj);
带有
// taken from the link above (macro expanded)
ar & boost::serialization::make_nvp( BOOST_PP_STRINGIZE(obj),boost::serialization::base_object<Base >(obj));
确实解决了这个问题。
顺便说一句,我发现了另一种类型的奇怪错误,它可能会出现并导致"流输入错误"。它是这样工作的:
如果层次结构中甚至有一个构造函数可以初始化变量(任何变量),但没有初始化,那么在尝试反序列化时会出现流输入错误。
如果一个类中没有变量,那么一切都可以。但如果只有一个变量,则必须在该类的构造函数中初始化至少一个变量!我不知道为什么这很重要,但这解决了我的一个主要问题。
我不是Boost序列化的专家。我只体验了两天。我遇到了和你相同的问题,在阅读了完整的文档后,我仍然没有成功地解决这个问题。但你的解决方案对我有效,让我想到了以下几点。
正如文档在"特殊注意事项/XML档案:"一章中所解释的那样
XML与其他格式的不同之处在于,它需要每个数据成员。我们的目标是将这些信息添加到类中序列化规范,同时仍然允许要与任何存档一起使用的序列化代码。这是通过以下方式实现的要求将序列化到XML存档的所有数据序列化为名称值对。
这意味着在使用XML归档时,每个字段都必须用一个名称保存。这就是为什么我们总是需要使用BOOST_SERIALIZATION_NVP
宏,它在XML文件中添加参数名称的字符串转换。
您的解决方案让我认为,即使对于基类的序列化,XML也需要一个与其关联的名称。boost::serialization::base_object<Base>
不能像BOOST_SERIALIZATION_NVP
那样提供自动名称,因此我们需要显式地为其提供函数:
template<class T> const nvp< T > boost::serialization::make_nvp(const char * name, T & t)
BOOST_PP_STRINGIZE(obj)
字符串表示参数obj
。在我的情况下,我更喜欢给出一个字符串:
ar & boost::serialization::make_nvp("MyBase", boost::serialization::base_object<Base>(obj));
这是我的理解。如果我是假的,请纠正我。
- 链表指针问题
- 指针问题:从不兼容的类型"int"分配给"int *"
- C++指针问题:如何修复这些代码中的错误?
- *++*++ppp,*++pp[1],*++(*(1+ppp)有什么具体的区别吗?(C/C++指针问题)
- C++ 入门加列表:10.9 "顶部"指针问题
- C++ 指针问题 - 通过方法更新指针
- 未分配正在释放的指针 - 指针问题
- 双指针问题通过函数传递错误
- 在C++中实现图形 DFS,指针问题
- 返回指针问题
- C++ - 有人有分析指针到指针问题的技巧吗?
- 选择排序指针问题
- 涉及删除操作的 C++ 指针问题
- 模板类指针问题 c++
- Swig和指针问题(python)
- 引用指针问题
- 函数指针问题
- 通过类型C++ 的继承树递归导致此指针问题
- 无法将文件读入字符数组(像往常一样,某些指针问题)
- 结构中的指针问题