So I can do:
Base* b = Base::create("DerivedClass");
I read this interesting post on Stackoverflow http://stackoverflow...c/534396#534396 (by epatel) but noticed he uses a factory singleton (Factory::instance()->registerCreator()).
Instead of a singleton I used a static varible. Here is my solution:
(C++)
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Base
{
public:
typedef Base* (*CreateFun)();
static Base* create(string name)
{
FunctionMap::iterator it = creators.find(name);
if (it == creators.end())
return NULL;
return (it->second)();
}
static bool reg(string name, CreateFun fun)
{
creators[name] = fun;
return true;
}
virtual ~Base() {}
private:
typedef map<string, CreateFun> FunctionMap;
static FunctionMap creators;
};
Base::FunctionMap Base::creators;
// this registers a derived class in the factory method of the base class
// it adds a factory function named create_NAME()
// and calls Base::reg() by the help of a dummy static variable to register the function
#define REGISTER( _name ) \
namespace { \
Base* create_ ## _name() { return new _name; } \
static bool _name ## _creator_registered = Base::reg(# _name, create_ ## _name); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class DerivA: public Base
{
public:
DerivA()
{
cout << "DerivA was created" << endl;
}
};
REGISTER(DerivA)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class DerivB: public Base
{
public:
DerivB()
{
cout << "DerivB was created" << endl;
}
};
REGISTER(DerivB)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
Base* b = Base::create("DerivA");
b = Base::create("DerivB");
return 0;
}
When you create a new derived class, all you need to do is to use the REGISTER() macro.
Note I don't have a separate factory class. I use the base class for this.
Note also that this code should be slightly modified if split into multiple files (multiple compilation units: no guarantee on the order of initialization of static variables).
Actually I want to use this as a component factory, so I can do something like
GameObject obj;
for each XML component node {
Component* comp = Component::createFromXml(node).
obj.addComponent( comp );
}
What do you think of this solution?
EDIT: having problems with identation