新:我可以在access.hpp中使用它吗?
template<class Archive, class T>
inline void serialize_adl(Archive &, T &, const unsigned int);
这表明我可以定义一个不同的序列化,将对象作为参数。
这样的代码会在下面改变吗?
我认为我的问题是如何添加序列化方法 接口类,它将调用序列化方法 派生子类。
class Interface {
public:
virtual void aVirtual() = 0;
private:
friend class boost::serialization::access;
template<class Archive, class T>
void serialize_adl(Archive & ar, T & object, const unsigned int version)
{
// Would this work?????
ar & object;
}
};
template<class T>
class Derived : Interface {
public:
Derived(T in) : m_data(in) {}
virtual void aVirtual() { // Do something }
private:
T m_data;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & m_data;
}
};
我目前从编译器中收到以下错误:
error C2039: 'serialize' : is not a member of 'Interface'
这是不寻常的,因为对象在智能指针内,所以它应该 知道它是什么类型:
std::unique_ptr<Interface> object = std::unique_ptr<Interface>(new Derived<int>(5));
因此,当我尝试序列化时:
archive >> *object;
因此我得到了错误。
答案 0 :(得分:4)
这里有两个问题:
您正在序列化模板类。这不是问题,是的,您可以通过ADL侵入(成员serialize
)或非侵入性(自由函数serialize
)。正如文档(Serializing Templates)所述,shared_ptr<T>
序列化的实现是非侵入式变体的一个很好的例子:
您正在通过多态指针序列化基类/派生类。对于序列化部分,这没什么特别的(你可以register_type
或者你可以在派生的base_object<Interface>(this)
函数中使用serialize
。
然而,在反序列化方面,您需要预测通过多态指针序列化的可能具体实例类型的完整列表。 BOOST_EXPORT_CLASS
宏是实现此目的的最简单方法。但是,您必须列出您希望支持的模板的具体实例:
BOOST_CLASS_EXPORT(Derived<std::string>)
BOOST_CLASS_EXPORT(Derived<double>)
BOOST_CLASS_EXPORT(Derived<int>) // include all subtypes we can expect in an input archive
或
BOOST_CLASS_EXPORT_GUID(Derived<std::string>, "4ef5a3ff-168a-4242-846b-4886f48424b5")
BOOST_CLASS_EXPORT_GUID(Derived<double>, "d0ed9de6-584f-476d-9898-8234bcb4efdb")
BOOST_CLASS_EXPORT_GUID(Derived<int>, "505538f0-2dd1-43bd-92a2-506ed9659bbe") // include all subtypes we can expect in an input archive
情况的复杂性 - 以及混乱 - 源于您通过多态指针序列化派生的类模板。一切都在同一时间。但从概念上讲,两者都很容易解决。
略有不相关,
- 是的,您可以使用免费功能序列化,请参阅下面的第3个替代版本。尽管如此,它几乎没有收获,只需要
m_data
可以公开访问。- 请勿使用
serialize_adl
,因为它是一个实施细节
以下是三个集成了所有内容的示例:
Live On Coliru - 原始Interface*
Live On Coliru - 与shared_ptr<Interface>
相同
Live On Coliru - 与非侵入式serialize
功能相同
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
class Interface {
public:
virtual void aVirtual() = 0;
virtual ~Interface() {}
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive&, unsigned) { }
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Interface)
template<class T>
class Derived : public Interface {
public:
Derived(T in = 0) : m_data(in) {}
virtual void aVirtual() { /*Do something*/ }
T const& getData() const { return m_data; }
private:
T m_data;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, unsigned)
{
ar & boost::serialization::base_object<Interface>(*this);
//// alternatively, if you don't want to make the abstract base serializable:
// boost::serialization::void_cast_register<Derived, Interface>();
ar & m_data;
}
};
BOOST_CLASS_EXPORT(Derived<std::string>)
BOOST_CLASS_EXPORT(Derived<double>)
BOOST_CLASS_EXPORT(Derived<int>) // include all subtypes we can expect in an input archive
int main()
{
std::stringstream ss;
{
boost::archive::text_oarchive oa(ss);
Interface* o = new Derived<int>(42);
oa << o;
delete o;
}
std::cout << "Serialized: '" << ss.str() << "'\n";
{
boost::archive::text_iarchive ia(ss);
Interface* o = nullptr;
ia >> o;
if (auto p = dynamic_cast<Derived<int>*>(o))
std::cout << "Deserialized into Derived<int> with data: " << p->getData() << "\n";
delete o;
}
}
示例输出:
Serialized: '22 serialization::archive 11 0 1 1 12 Derived<int> 1 0
0 42
'
Deserialized into Derived<int> with data: 42
答案 1 :(得分:0)
答案 2 :(得分:-1)
您应该仅序列化派生对象。使用dynamic_cast进行类型转换
class Interface {
virtual void f() = 0;
};
template<class T> class Derived : public Interface {
T m_data; void f(){};
};
Interface* object = new Derived<Type>();
Derived<Type>* objectSer = dynamic_cast<Derived<Type>*>(object);
//serialization
std::ofstream ofs("filename");
boost::archive::text_oarchive oa(ofs); oa << *objectSer;