我正在使用 boost:serialization 将数据结构保存到文件中。实际数据是类和子类的指针向量。然而,被序列化的类的构造函数将另一个实例化类 Agent 作为参数,该类 Agent 是一个控制与模拟 API(webbots)通信的对象。我看到在 boost::serialization 示例中,可序列化的对象需要一个空的构造函数 class() {}; 用于重建。然而,这在我的情况下是不切实际的。如何使用重建但包含与 API 通信的对象?可序列化类之一具有以下构造函数:
State(Agent &A, ACTION_MODE const& m);
我从 boost docs 中的示例中看到我需要这样的东西:
State() {};
然而 Agent &A 必须作为参数传递。我应该找到解决这个问题的方法(使用外部、单例、全局对象)还是有办法在重建时修改这种行为?我确定我在这里遗漏了一些东西。
谢谢
编辑:也许我解释得不够清楚。尝试通过重建序列化数据来“加载”时收到错误消息。
error: no matching function to call State::State()
这就是让我研究 boost::serialize 代码的原因,并认为它正在调用构造函数或复制运算符。如何使它使用特定的构造函数来序列化数据并将代理引用 &a 作为参数?
编辑#2:
template <class S, class P, class A> void Task<S,P,A>::save(const char* file)
{
std::ofstream ofs(file);
assert(ofs.good());
boost::archive::text_oarchive oa(ofs);
oa << states;
ofs.close();
}
template <class S, class P, class A> void Task<S,P,A>::load(const char* file)
{
std::ifstream ifs(file);
boost::archive::text_iarchive ia(ifs);
ia >> states;
ifs.close();
}
States 是 boost::serialization::access 的朋友,并且有一个函数 serialize。保存工作正常,加载是问题。states 是:boost::ptr_vector<S> states;
其中 S 是 State 多态类的一种类型。
状态是基类并且具有“序列化”
template <class Archive>
void State::serialize(Archive& ar, const unsigned int version)
{
ar & accel.Xaxis & accel.Yaxis & accel.Zaxis;
ar & gyro.Xaxis & gyro.Yaxis & gyro.Zaxis;
ar & gps.Yaxis;
ar & positions;
ar & reward & value & hash_value;
}
guState 继承自 State。
template <class Archive>
void guState::serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<State>(*this);
ar & accel.Xaxis & accel.Yaxis & accel.Zaxis;
ar & gyro.Xaxis & gyro.Yaxis & gyro.Zaxis;
ar & gps.Yaxis;
ar & positions;
ar & reward & value & hash_value;
}
accel、gyro、gps 是具有 3 个双变量的简单结构。它们在上面被序列化^^。职位是一个std::map<std::string,float> positions;
查看序列化的文本文件,一切正常。我不明白为什么它在尝试加载文件时调用构造函数。
编辑#3:
基本构造函数是:
State(Agent &A, ACTION_MODE const& m);
派生构造函数是:
guState::guState(Agent& A, ACTION_MODE const& m) :
State(A, m)
{
...
}
每个状态(或派生状态)中保存的代理引用 &A 指的是从模拟 API 获得的对象。它控制一个机器人。我无法序列化它,序列化它没有意义。
当我使用:
namespace boost { namespace serialization {
template <class Archive>
void save_construct_data(Archive & ar,const guState* d,const unsigned int file_version)
{
ar << guState::caller;
ar << guState::mode;
}
template <class Archive>
void load_construct_data(Archive & ar, guState* d,const unsigned int file_version)
{
Agent &a;
ACTION_MODE &m;
ar >> a;
ar >> m;
::new(d) guState(a,m);
}
}
}
我收到以下错误:
invalid use of non-static data member State::caller
invalid use of non-static data member State::mode
指的是构造函数中使用的引用。和:
error: 'a' declared as reference but not initialized
error: 'm' declared as reference but not initialized
如您所见,尝试保存对 Agent 的引用是没有意义的,因为每次启动应用程序时,该引用(即使可以保存或序列化)都可能不同。
并且在加载构造数据时,除了我可能使用了错误的语法之外,从对代理的序列化引用进行构造是没有意义的。
我相信我需要的是一种告诉 load_construct_data 如何获取对代理的引用(在初始化代理对象之后)并使用该引用来构造数据的方法。
这有任何意义吗 ?你认为这是可行的吗?
编辑#4
namespace boost { namespace serialization {
template <class Archive>
void save_construct_data(Archive & ar,const guState* d,const unsigned int file_version)
{
ar << guState::caller;
}
template <class Archive>
void load_construct_data(Archive & ar, guState* d,const unsigned int file_version)
{
Agent * a;
ACTION_MODE mode = RAND_SING;
ar >> a;
::new(d) guState(*a,mode);
}
}
}
它不允许序列化 guState::caller
我还使类 Agent 可序列化,并重载了 Agent 的 load_construct_data 和 save_construct_data,以便从模拟应用程序请求新的 Agent 实例来控制 API。