An easier way to create factories is to use a template to create the factory method and then store it using a function pointer or perhaps boost::function
or std::function
if they're available.
For example, given the objects:
#include <iostream>
struct GameObject {
virtual ~GameObject() {}
virtual void foo() const = 0;
};
struct ExampleObject : GameObject {
void foo() const { std::cout << "ExampleObject::foo\n"; }
};
We can use a template to define a generic object factory:
template <typename Object>
GameObject* object_factory() const
{
return new Object();
};
Define a vector to store function pointers to factory methods:
#include <vector>
typedef GameObject*(*factory_ptr)();
std::vector<factory_ptr> factories;
Then add an object to the factories using something like:
int example_object_id = factories.size();
factories.push_back(&object_factory<ExampleObject>);
And then later create the object with:
GameObject* obj = factories[example_object_id]();
Here's a complete example:
#include <iostream>
#include <vector>
template <typename BaseObject>
class game_object_factory
{
template <typename Object>
static BaseObject* create_object()
{
return new Object();
};
typedef BaseObject*(*factory)();
std::vector<factory> factories;
public:
template <typename Object>
int register_type()
{
int index = factories.size();
factories.push_back(&create_object<Object>);
return index;
}
BaseObject* create(int id) const {
return factories[id]();
}
};
struct GameObject {
virtual ~GameObject() {}
virtual void foo() const = 0;
};
struct Example1 : GameObject {
void foo() const { std::cout << "Example1::foo\n"; }
};
struct Example2 : GameObject {
void foo() const { std::cout << "Example2::foo\n"; }
};
int main() {
game_object_factory<GameObject> factory;
int obj1_id = factory.register_type<Example1>();
int obj2_id = factory.register_type<Example2>();
// Should use a smart pointer here to simplify memory management.
GameObject* obj = factory.create(obj2_id);
obj->foo();
delete obj;
}