【发布时间】:2019-11-20 21:38:24
【问题描述】:
我有一段代码在其中定义了以下类:Base、Derived、Contaienr。
Derived 显然继承了Base,而Container 包含Base 共享指针的向量,可以是Base 和Derived 的指针。
我想序列化Container,因此向量的元素分别序列化为Base 和Derived,但它似乎不起作用。
这是我的测试代码:
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/export.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <sstream>
/// Base class ///
class Base {
public:
using Ptr = std::shared_ptr<Base>;
public:
void setDouble(double d) {
m_d = d;
}
void setInteger(int c) {
m_c = c;
}
double getDouble() const {
return m_d;
}
int getInteger() const {
return m_c;
}
private:
double m_d;
int m_c;
};
/// Derived class from Base ///
class Derived : public Base {
public:
using Ptr = std::shared_ptr<Derived>;
public:
void setString(const std::string& s) {
m_s = s;
}
const std::string& getString() const {
return m_s;
}
private:
std::string m_s;
};
/// Container of base class pointers ///
class Container {
public:
void addData(Base::Ptr data) {
m_data.push_back(data);
}
const std::vector<Base::Ptr>& getDataVector() const {
return m_data;
}
private:
std::vector<Base::Ptr> m_data;
};
BOOST_SERIALIZATION_SPLIT_FREE(Base)
BOOST_SERIALIZATION_SPLIT_FREE(Derived)
BOOST_SERIALIZATION_SPLIT_FREE(Container)
BOOST_CLASS_EXPORT_GUID(Derived, "Derived")
namespace boost {
namespace serialization {
/// Serialization of base class ///
template<class Archive>
void save(Archive& ar, const Base& m, unsigned int) {
auto d = m.getDouble();
auto i = m.getInteger();
ar& make_nvp("doublevalue", d);
ar& make_nvp("intvalue", i);
}
template<class Archive>
void load(Archive& ar, Base& m, unsigned int) {
double d;
int i;
ar& make_nvp("doublevalue", d);
ar& make_nvp("intvalue", i);
m.setDouble(d);
m.setInteger(i);
}
/// serialization of derived class ///
template<class Archive>
void save(Archive& ar, const Derived& m, unsigned int) {
ar& make_nvp("base", base_object<const Base>(m));
ar& make_nvp("stringvalue", m.getString());
}
template<class Archive>
void load(Archive& ar, Derived& m, unsigned int) {
std::string s;
ar& make_nvp("base", base_object<Base>(m));
ar& make_nvp("stringvalue", s);
m.setString(s);
}
/// serialization of container class ///
template<class Archive>
void save(Archive& ar, const Container& m, unsigned int) {
ar& make_nvp("data", m.getDataVector());
}
template<class Archive>
void load(Archive& ar, Container& m, unsigned int) {
std::vector<Base::Ptr> data;
ar& make_nvp("data", data);
for (const auto& it : data) {
m.addData(it);
}
}
}
} // namespace boost::serialization
int main(int argc, char *argv[]) {
// Initialize container
Container container;
auto baseObj = std::make_shared<Base>();
baseObj->setDouble(4.3);
baseObj->setInteger(6);
auto derivedObj = std::make_shared<Derived>();
derivedObj->setDouble(1.1);
derivedObj->setInteger(2);
derivedObj->setString("string in derived");
container.addData(baseObj);
container.addData(derivedObj);
// Print serialization of Base
std::stringstream basess;
boost::archive::xml_oarchive baseoa{basess};
baseoa << boost::serialization::make_nvp("baseclass", baseObj);
std::cout << basess.str() << std::endl;
// Print serialization of Derived
std::stringstream derivedss;
boost::archive::xml_oarchive derivedoa{derivedss};
derivedoa << boost::serialization::make_nvp("derivedclass", derivedObj);
std::cout << derivedss.str() << std::endl;
// Print serialization of Container
std::stringstream containerss;
boost::archive::xml_oarchive containeroa{containerss};
containeroa << boost::serialization::make_nvp("containerclass", container);
std::cout << containerss.str() << std::endl;
return 0;
}
当我运行程序时,我打印baseObj 的序列化,这是Base 的共享指针:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="17">
<baseclass class_id="0" tracking_level="0" version="1">
<px class_id="1" tracking_level="1" version="0" object_id="_0">
<doublevalue>4.29999999999999982e+00</doublevalue>
<intvalue>6</intvalue>
</px>
</baseclass>
这似乎是正确的,因为我在基类中同时定义了 doublevalue 和 intvalue。
然后我打印derivedObj 的序列化,这是Derived 的共享指针:
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="17">
<derivedclass class_id="0" tracking_level="0" version="1">
<px class_id="1" tracking_level="1" version="0" object_id="_0">
<base class_id="2" tracking_level="1" version="0" object_id="_1">
<doublevalue>1.10000000000000009e+00</doublevalue>
<intvalue>2</intvalue>
</base>
<stringvalue>string in derived</stringvalue>
</px>
</derivedclass>
它似乎按预期工作,因为我有基类数据,还有派生类的stringvalue。
现在,如果我将两个指针都放入 Container 中的 std::vector<std::shared_ptr<Base>> 中,我期望正确地序列化 baseObj 和 derivedObj。相反,这是输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="17">
<containerclass class_id="0" tracking_level="0" version="0">
<data class_id="1" tracking_level="0" version="0">
<count>2</count>
<item_version>1</item_version>
<item class_id="2" tracking_level="0" version="1">
<px class_id="3" tracking_level="1" version="0" object_id="_0">
<doublevalue>4.29999999999999982e+00</doublevalue>
<intvalue>6</intvalue>
</px>
</item>
<item>
<px class_id_reference="3" object_id="_1">
<doublevalue>1.10000000000000009e+00</doublevalue>
<intvalue>2</intvalue>
</px>
</item>
</data>
</containerclass>
vector 的两个元素都被序列化为Base 指针。
我已尝试按照文档中的建议使用 BOOST_CLASS_EXPORT_GUID(Derived, "Derived") 宏,但它似乎不起作用。
我也尝试了this post 中提出的解决方案,通过注释BOOST_CLASS_EXPORT_GUID(Derived, "Derived") 并在Container 的序列化中使用register_type,但问题仍然存在:
/// serialization of container class ///
template<class Archive>
void save(Archive& ar, const Container& m, unsigned int) {
ar.template register_type<Derived>();
ar& make_nvp("data", m.getDataVector());
}
template<class Archive>
void load(Archive& ar, Container& m, unsigned int) {
ar.template register_type<Derived>() ;
std::vector<Base::Ptr> data;
ar& make_nvp("data", data);
for (const auto& it : data) {
m.addData(it);
}
}
如何正确序列化存储在Base 的共享指针向量中的Derived 类?
【问题讨论】:
-
我想你可能会感兴趣:stackoverflow.com/a/30210929/4658169
-
您需要保存矢量大小而不是每个对象数据 Derived + Base 然后在加载时获取并使用您加载的信息重建它们并插入到容器中
标签: c++ serialization boost boost-serialization