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