Re: Object (de)serialization
Am 25.01.2010 20:31, schrieb Philip Pemberton:
On Mon, 25 Jan 2010 05:13:01 -0800, Brian wrote:
class Triangle : public Shape {
public:
Triangle() {
cerr<<"ctor: Triangle\n";
creationMap["triangle"] = new
Triangle();
}
That default constructor looks like trouble. Perhaps you could move the
second line to another function.
[...]
Now back to the deserialisation problem...
At this point I haven't even managed to get an example implementation of
the C++FAQ deserialiser working -- the static ctors aren't being called,
so the std::map doesn't contain anything, thus the code bombs (current
version throws an exception, the one I posted segfaults)...
The map isn't filled because you don't create triangle, so the line
creationMap["triangle"] = new Triangle();
isn't executed. You have to move this line somewhere else so that it's
invoked before you use creationMap, like a registerShape function
that'll be called from main.
But instead using this prototype based meachanism, I suggest using a
factory functor and storing a boost::function in creationMap, if you
have access to Boost (std::tr1::function is the same). Example:
#include <map>
#include <string>
#include <iostream>
#include <boost/function.hpp>
using namespace std;
class Shape {
public:
Shape() { cerr << "ctor: Shape\n"; };
static Shape* deserialise(string data) {
return creationMap[data]();
}
// add virtual d'tor to allow typeid / delete through base pointer
virtual ~Shape() {}
protected:
typedef boost::function<Shape*()> creation_func;
static void registerShape(std::string type, creation_func factory) {
creationMap[type] = factory;
}
template <typename T>
static Shape* create() {
return new T;
}
private:
static std::map<std::string, creation_func> creationMap;
};
/*static*/ std::map<std::string, Shape::creation_func> Shape::creationMap;
class Triangle : public Shape {
public:
Triangle() {
cerr << "ctor: Triangle\n";
}
static void registerClass() {
registerShape("triangle", &Shape::create<Triangle>);
}
};
int main()
{
Triangle::registerClass();
Shape *x = Shape::deserialise("triangle");
// checks if x has correct type:
cerr << typeid(*x).name() << endl;
delete x;
}
--
Thomas