"Patrick Stinson" <aj*****@gci.ne t> wrote in message
news:10******** *****@corp.supe rnews.com...
I am trying to create a way to register static members of a **class**, not
an object, for making an object factory. The main thing I want is to be
able to make a call like
class MyClass
{
public:
MyClass *factory();
};
register(MyClas s);
and have a method that calls MyClass::factor y() to return a MyClass object
on a call like 'MyClass *o = create("MyClass ");'.
Is there any C++ construct that would allow this sort of class
registration? I'd be into using macros and even templates (hopefully not).
Here is a longer example...
main.cpp:
------------------------------------------
#include <map>
#include <typeinfo>
typedef std::map<const char *, void (something::*)( )> FactoryMap;
FactoryMap *getMap()
{
// I need there to be exactly one instance of registry.
static FactoryMap registry;
return ®istry;
}
int register(someth ing Class)
{
pair<const char *, void (something::*)( )> p(typeid(Class) .name(),
Class::factory) ;
getMap()->insert(p);
}
void *create(const char *classname)
{
FactoryMap::ite rator it = getMap()->find(classname );
if(it != getMap()->end())
return it->second();
else
return NULL;
}
class A
{
public:
static A *factory(){retu rn new A;}
};
int aDummy = register(A); // THIS IS THE SORT OF CALL I'M AFTER
class B : public A
{
public:
static A *factory(){retu rn new B;}
};
int bDummy = register(B); // AGAIN, THIS IS THE SORT OF CALL I'M AFTER
int main()
{
A *a = *b
}
Patrick,
here's an outline of a solution - basically I've used templates to make
factory objects out of
your classes so I can call their static methods through a virtual function.
The registration
process creates a mapping of factory to name, so you can do
factory.create( "foobar").
dave
#include <stdio.h>
#include <string>
#include <map>
using namespace std;
class MyClass
{
public:
virtual void dofoo()=0;
};
class ClassFactory
{
public:
virtual MyClass* create()=0;
virtual string name()=0;
};
template < class T >
class FactoryWrapper : public ClassFactory
{
public:
virtual MyClass* create(){ return T::create();}
virtual string name(){ return T::name();}
};
class Factories
{
public:
void registerFactory ( ClassFactory* factory)
{
_facts[factory->name()]=factory;
}
MyClass* create( const string& name)
{
if ( _facts[name] )
{
return _facts[name]->create();
}
return 0;
}
map<string, ClassFactory*> _facts;
};
class Class1 : public MyClass
{
public:
static Class1* create(){ return new Class1();};
virtual void dofoo(){ printf("Class1: :dofoo\n");};
static string name(){ return "Class1";} ;
};
class Class2 : public MyClass
{
public:
static Class2* create(){ return new Class2();};
virtual void dofoo(){ printf("Class2: :dofoo\n");};
static string name(){ return "Class2";} ;
};
int main(int argc, char* argv[])
{
FactoryWrapper< Class1> class1Factory;
FactoryWrapper< Class2> class2Factory;
Factories factories;
factories.regis terFactory(&cla ss1Factory);
factories.regis terFactory(&cla ss2Factory);
MyClass* c1= factories.creat e("Class1");
MyClass* c2= factories.creat e("Class2");
c1->dofoo();
c2->dofoo();
return 0;
}