【发布时间】:2011-07-18 14:51:54
【问题描述】:
我正在使用 boost:serialization 将数据结构保存到文件中。实际数据是类和子类的指针向量。 然而,被序列化的类的构造函数将另一个实例化类 Agent 作为参数,该类 Agent 是一个控制与模拟 API(webbots)通信的对象。 我看到在 boost::serialization 示例中,可序列化的对象需要一个空的构造函数 class() {};用于重建。然而,这在我的情况下是不切实际的。如何使用重建但包含与 API 通信的对象? 其中一个可序列化的类有这个构造函数:
State(Agent &A, ACTION_MODE const& m);
我从 boost 文档中的示例中看到我需要这样的东西:
State() {};
但代理 &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 的朋友,并且有一个函数序列化。
保存工作正常,加载是问题。
states 是:boost::ptr_vector<S> states; 其中 S 是 State 多态类的一种类型。
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)
{
...
}
Agent 引用 &A,保存在每个 State(或派生 State)中,指的是从模拟 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。
【问题讨论】:
-
你能发布你的
load产生错误的函数吗? -
能不能把状态类和基类的序列化函数也贴出来。
-
另外,当你这样做时,你能否在我的回答中添加评论,以便我知道你已经完成了。
-
@Tom 我已经添加了您要求的代码。感谢您的帮助。
-
没问题。也可能值得逐个构建简单的可编译示例,直到它与您想要做的事情相匹配。破坏有效的东西总是比修复无效的东西更容易,然后如果你卡住了,你就会知道问题出在哪里,并且你有一个最小的例子来发布你的下一个问题。