我不允许在头文件中放置任何(模板)函数定义。我有一个没有标准构造函数的类。
为了使序列化在没有构造函数的情况下工作,我使用了save_construct_data
和load_construct_data
。我在头文件中有这样的声明。但是它们似乎没有与cpp文件中的定义链接起来。我的意思是,serialize
函数链接了,但是实际上并没有进行很多序列化。
声明:
// Foo.h
#include <boost/serialization/access.hpp>
#include <boost/serialization/export.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <iostream>
class Foo {
friend class boost::serialization::access;
int m_bar;
template<class Archive>
void serialize(Archive & ar, const unsigned int file_version);
public:
Foo(int bar);
int getBar() const;
};
BOOST_CLASS_EXPORT(Foo);
namespace boost_1_69_0 {
namespace serialization {
template<class Archive>
void save_construct_data(Archive& ar, const Foo* t, const unsigned int version);
template<class Archive>
void load_construct_data(Archive& ar, Foo* t, const unsigned int version);
}
}
定义:
x一个一个一个一个x一个一个二个x
哦,顺便说一句,我不知道为什么,但是如果我调用名称空间boost
而不是boost_1_69_0
,我会得到错误:error: namespace alias ‘boost’ not allowed here, assuming ‘boost_1_69_0’
,我不知道为什么。
1条答案
按热度按时间dtcbnfnu1#
有很多事情(除了我们前面讨论过的boost_1_69_0之外)。
1.首先,在
Foo.cpp
中定义专门化:但是这样的模板并不存在,只有成员函数模板
serialize
,另外,你可以示例化任何你想要的,但是除非它在头文件中是**extern
-declared**,否则编译器将拒绝示例化没有定义的模板。1.加载/保存构造数据函数也会发生同样的情况(缺少外部声明)。
1.您选择将load/save构造数据放在
boost::serialization
名称空间中,这很奇怪,因为显然您希望在头文件中隐藏实现细节,我会在最少干扰和最少紧密耦合的位置定义函数:在类命名空间中。BOOST_CLASS_EXPORT(Foo)
也有类似的情况--因为这是在头文件中,所以您将在多个翻译单元中定义内容。通过分离声明和定义来避免它(或者,你知道,选择不做这种雨舞)
1.顶级
const
在函数签名中(字面上)毫无意义1.为什么你要在头文件中包含整个归档文件呢?我得说包含这些文件比包含你试图隐藏的模板函数的定义要有100倍的影响力...
1.与
iostream
相同1.你正在导出一个非多态类。这将无法编译。你需要一个虚拟接口。
1.你没有通过指针进行序列化;多态类型没有意义,加载/保存构造数据也没有意义
运行这些代码,我会得到以下"更理想"的标题:
相应的实现:
现在,稍微修正一下
main
:图纸:
看它**Live On Wandbox**
奖金
如果你真的隐藏了实现,为什么不完全隐藏它呢?那更容易,可以虚拟化等等。它伤害了我的感情,你要去这些长度"隐藏"的细节,但仍然包括主程序内的存档类型...并允许用户不匹配的序列化/反序列化,例如通过使用不同的XML名称,或者完全不同的变量类型(这导致未定义的行为)。
让我们制作一个理想的标题:
我希望你会同意,* 这 * 是削减依赖性和减少耦合。其余的只是口头上的服务。
现在所有真正与序列化相关的东西都可以在cpp中了,在一个真实的项目中,你会有一个TU专门用来序列化整个对象图(最简单的方法就是把它放在
IFoo.cpp
中)。让我们加入
base_object
序列化(以前没有):扩展
main
以显示往返反序列化:图纸
再看一遍**Live On Wandbox**。