在我将其实现到项目中之前,我编写了一个示例程序来弄清楚Boost的序列化库,但是,我有一些无法解释的行为。
在我的示例中,我有两个类:通用BaseClass
和专用DerivedClass
(类似于我计划使用Boost的方式)。 BaseClass
只有一个成员,即名为name
的字符串,默认为“ BaseClass”。 DerivedClass
公开继承BaseClass
,将name
设置为其他内容,并拥有自己的唯一成员data
。
在主程序中,我创建了一个DerivedClass
,其中data
设置为“特别酷的东西”,并创建了一个BaseClass
,其中name
是“常规的东西”。我将这两个都用boost::archive::text_oarchive
写入文件,然后读回第一个对象DerivedClass
两次(两次都创建std::ifstream
)。第一次读回去时,我将其放在BaseClass*
中。调用BaseClass::printData()
(一种打印std::typeid
和name
的虚拟方法)将打印出以下内容:
--- Storage done, now loading the first object as BaseClass ---
9BaseClass: 0
接下来,当我将其加载为DerivedClass*
并调用DerivedClass::printData()
(从BaseClass
覆盖以在输出中包括成员data
)时,正确打印:< / p>
--- Storage done, now loading the first object as DerivedClass ---
12DerivedClass: DerivedClass AND special cool stuff
在我正在写的文件中,我看到了:
22 serialization::archive 15 0 1 0
0 1 0
1 12 DerivedClass 18 special cool stuff 1
2 13 regular stuff
当我在原始序列中BaseClass::printData()
上调用DerivedClass
时,我得到了:
9BaseClass: DerivedClass
很显然,DerivedClass
已正确存储。关于将其作为BaseClass
加载以检查name
的某些事情搞砸了。我想不出为什么它会给我一个包含std::string
的{{1}}。
我才刚刚开始学习如何使用该库,我在网上发现的大多数类似问题和文档都没有效果(即,尽管使用0
或BOOST_EXPORT_CLASS
很可能是我使用不正确)。
这是我的代码:
BOOST_CLASS_TYPE_INFO
#include <iostream>
#include <fstream>
#include <string>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/nvp.hpp>
#include "baseclass.h"
#include "derivedclass.h"
int main() {
BaseClass* testBase = new BaseClass("regular stuff");
DerivedClass* testDerivate = new DerivedClass("special cool stuff");
testDerivate->BaseClass::printData();
std::cout << std::endl << " --- " << "Storing objects in the file 'output'..." << " --- " << std::endl;
std::ofstream output("storage");
{
boost::archive::text_oarchive boost_out(output);
boost_out << (testDerivate);
testDerivate->printData();
boost_out << (testBase);
testBase->printData();
}
std::cout << std::endl << " --- " << "Storage done, now loading the first object as BaseClass" << " --- " << std::endl;
{
std::ifstream input("storage");
BaseClass* base;
boost::archive::text_iarchive boost_in(input);
boost_in >> (base);
base->printData();
input.close();
}
std::cout << std::endl << " --- " << "Storage done, now loading the first object as DerivedClass" << " --- " << std::endl;
{
std::ifstream input("storage");
DerivedClass* derive;
boost::archive::text_iarchive boost_in(input);
boost_in >> (derive);
derive->printData();
input.close();
}
return 0;
}
#pragma once
#include <string>
#include <iostream>
#include <typeinfo>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
class BaseClass
{
public:
BaseClass() {
name = "BaseClass";
}
BaseClass(std::string custom) {
name = custom;
}
virtual ~BaseClass() {}
virtual void printData() {
std::cout << typeid(*this).name() << ": " << name << std::endl;
}
protected:
std::string name;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & (name);
}
};
很抱歉,如果这有点长,我想尽可能地描述一下。我对使用Boost还是很陌生,对C ++并不是很了解,所以即使您对我的代码有一些一般性的评论,也还是会感激的。
答案 0 :(得分:1)
您没有加载与序列化相同的 types 。
所以,可以说:
Base* b = new Derived();
boost_out << b;
并反序列化:
Base* b = nullptr;
boost_in >> b;
您无法序列化Derived*
并将其反序列化为Base*
,反之亦然。
因此,如果您知道接收代码必须支持所有派生类,请使其明确并序列化Base*
。
要让反序列化端知道在反序列化多态基址指针时可能遇到的一组派生类型集,请导出类型。
另请参见https://www.boost.org/doc/libs/1_67_0/libs/serialization/doc/special.html#export:
在{a.hpp“标头中本身包含
BOOST_CLASS_EXPORT
就像其他序列化特征一样,将导致在调用BOOST_CLASS_EXPORT
之前很难或不可能遵循上述有关包含存档标头的规则。最好通过在标题声明中使用BOOST_CLASS_EXPORT_KEY
和在类定义文件中使用BOOST_CLASS_EXPORT_IMPLEMENT
来解决。[...片段...]
将
BOOST_CLASS_EXPORT
放在库代码中将无效,除非还包括存档类标头。因此,在构建库时,应包括他预期使用的所有存档类的所有标头。或者,可以仅包含Polymoprhic [sic] 档案的标头。
main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/nvp.hpp>
//#include <boost/serialization/export.hpp>
#include "baseclass.h"
#include "derivedclass.h"
int main() {
BaseClass* testBase = new BaseClass("regular stuff");
BaseClass* testDerived = new DerivedClass("special cool stuff");
std::cout << std::endl << " --- " << "Storing objects in the file 'output'..." << " --- " << std::endl;
{
std::ofstream output("storage");
boost::archive::text_oarchive boost_out(output);
boost_out << testBase << testDerived;
}
std::cout << std::endl << " --- " << "Storage done, now loading the first object as BaseClass" << " --- " << std::endl;
{
std::ifstream input("storage");
BaseClass* b1;
BaseClass* b2;
boost::archive::text_iarchive boost_in(input);
boost_in >> b1 >> b2;
std::cout << "b1: "; b1->printData();
std::cout << "b2: "; b2->printData();
}
}
baseclass.h
#pragma once
#include <string>
#include <iostream>
#include <typeinfo>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>
class BaseClass
{
public:
BaseClass() {
name = "BaseClass";
}
BaseClass(std::string custom) {
name = custom;
}
virtual ~BaseClass() {}
virtual void printData() {
std::cout << typeid(*this).name() << ": " << name << std::endl;
}
protected:
std::string name;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned) {
ar & (name);
}
};
BOOST_CLASS_EXPORT_KEY2(BaseClass, "BaseClass");
baseclass.cpp
#include "baseclass.h"
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
BOOST_CLASS_EXPORT_IMPLEMENT(BaseClass)
derivedclass.h
#pragma once
#include <string>
#include <iostream>
#include <typeinfo>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/export.hpp>
#include "baseclass.h"
class DerivedClass : public BaseClass
{
public:
DerivedClass() : BaseClass("DerivedClass") {}
DerivedClass(std::string custom) : BaseClass("DerivedClass") {
data = custom;
}
virtual ~DerivedClass() {}
void printData() override {
std::cout << typeid(*this).name() << ": " << name << " AND " << data << std::endl;
}
protected:
std::string data;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned) {
ar & (boost::serialization::base_object<BaseClass>(*this));
ar & (data);
}
};
BOOST_CLASS_EXPORT_KEY2(DerivedClass, "DerivedClass");
derivedclass.cpp
#include "derivedclass.h"
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
BOOST_CLASS_EXPORT_IMPLEMENT(DerivedClass)
输出: