我正在尝试序列化指向多态类Shape
的指针。所以我需要使用BOOST_CLASS_EXPORT
macro为每个子类定义一个GUID。问题:在哪里放?
首先让我展示一个最小的测试用例:
shapes.hpp
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
class Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
// nothing to do
}
public:
virtual ~Shape() { }
};
class Rect : public Shape {
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive &ar, unsigned int const version) {
ar & boost::serialization::base_object<Shape>(*this);
}
public:
virtual ~Rect() { }
};
#ifdef EXPORT_IN_HEADER
BOOST_CLASS_EXPORT(Rect)
#endif
export.cpp
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_OBJECT
BOOST_CLASS_EXPORT(Rect)
#endif
的main.cpp
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include "shapes.hpp"
#ifdef EXPORT_IN_MAIN
BOOST_CLASS_EXPORT(Rect)
#endif
int main() {
Shape *shape = new Rect();
boost::archive::text_oarchive ar(std::cout);
ar << shape;
}
在gcc上,我用
编译它们g++ -omain main.cpp export.cpp -Wl,-Bstatic -lboost_serialization-mt -Wl,-Bdynamic -DEXPORT_IN_XXX
在这里,export.cpp
可能看起来有点傻。在我的实际情况中,它包含一个使用PIMPL惯用语的封闭类,并尝试序列化其(多态)Shape
实现。重要的是:BOOST_CLASS_EXPORT
可能位于不同的目标文件中,而不是调用序列化的代码。
所以这就是问题:在哪里使用BOOST_CLASS_EXPORT
?我有三个选项,可以使用EXPORT_IN_XXX
宏启用。
EXPORT_IN_MAIN
有效,但不是我想要的。调用序列化的代码不需要知道PIMPL类的实现细节。
EXPORT_IN_OBJECT
编译,但不起作用:它会生成boost::archive::archive_exception
消息unregistered void cast
。根据{{3}},这应该通过使用boost::serialization::base_object
序列化基类来解决,就像我一样,但它没有帮助。
EXPORT_IN_HEADER
甚至没有编译。宏BOOST_CLASS_EXPORT
扩展为模板特化(我们希望在头文件中),但也扩展到其中的静态成员的定义。所以我收到关于multiple definition of 'boost::archive::detail::init_guid<Rect>::guid_initializer'
。
如果重要,我正在使用g ++ 4.4.3和Boost 1.40。
答案 0 :(得分:8)
Exporting Class Serialization声明如下:
BOOST_CLASS_EXPORT
同样如此 源模块,包括任何一个 归档类头将实例化 代码[...]注意这个的实现 功能要求 出现
BOOST_CLASS_EXPORT
宏 之后并包含任何存档 代码所在的类头 实例化。所以,使用的代码BOOST_CLASS_EXPORT
看起来像 以下内容:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
... // other archives
#include "a.hpp" // header declaration for class a
BOOST_CLASS_EXPORT(a)
... // other class headers and exports
[...]包括
BOOST_CLASS_EXPORT
“a.hpp”标题就像人们一样 做其他序列化特征 将使困难或不可能 遵循上述规则 之前包含归档标头 调用BOOST_CLASS_EXPORT
。这个 可以通过使用最好地解决 标题中为BOOST_CLASS_EXPORT_KEY
声明和BOOST_CLASS_EXPORT_IMPLEMENT
在 类定义文件。
答案 1 :(得分:5)
我最终将所有序列化代码放在标头s11n.h
中,该标头包含在调用序列化的CPP文件中。基本上,我在上面概述了EXPORT_IN_MAIN
场景,但在不同文件中使用BOOST_CLASS_EXPORT
宏调用。
只有当只有一个编译单元包含s11n.h
时才会起作用,所以虽然它现在有用,但它并不是真正的解决方案......
答案 2 :(得分:2)
您可以使用EXPORT_IN_OBJECT,但包含BOOST_CLASS_EXPORT的文件还必须包含计划使用的所有归档hpp文件。
这是因为BOOST_CLASS_EXPORT宏注册了它认为您将使用的每个存档的派生类型信息(根据您包含的存档隐式确定)。
在您的示例中,使用EXPORT_IN_OBJECT但也添加#include to export.cpp。
在我们的代码中,我们创建了archives.hpp,其中包含我们使用的档案,并将其包含在我们需要使用BOOST_CLASS_EXPORT的地方。 (这样我们就有一份正式的档案清单。)
缺点是当我们决定使用新的存档类型时,我们需要重建所有内容,但我们发现它比多态存档支持更容易使用。
答案 3 :(得分:1)
答案 4 :(得分:0)
您可以为每个.cpp使用和唯一的BOOST_CLASS_EXPORT_GUID() 并仅在.cpp中添加它。不是.h
答案 5 :(得分:0)
这个问题让我疯狂,直到我意识到我的基类不是多态的。换句话说,它从未在任何地方使用关键字“虚拟”。因为我不需要多态行为。
以下是我修复它的方法:
在我的派生类的.cpp文件中,我添加了以下内容:
#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT(testnamespace::derivedclass)
这就是我必须做的一切。