Class object factories, references to a **class**

  • Thread starter Patrick Stinson
  • Start date
P

Patrick Stinson

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(MyClass);

and have a method that calls MyClass::factory() 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 &registry;
}

int register(something Class)
{
pair<const char *, void (something::*)()> p(typeid(Class).name(),
Class::factory);

getMap()->insert(p);
}

void *create(const char *classname)
{
FactoryMap::iterator it = getMap()->find(classname);
if(it != getMap()->end())
return it->second();
else
return NULL;
}

class A
{
public:
static A *factory(){return new A;}
};
int aDummy = register(A); // THIS IS THE SORT OF CALL I'M AFTER


class B : public A
{
public:
static A *factory(){return new B;}
};
int bDummy = register(B); // AGAIN, THIS IS THE SORT OF CALL I'M AFTER

int main()
{
A *a = *b
}
 
D

Dave Townsend

Patrick Stinson said:
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(MyClass);

and have a method that calls MyClass::factory() 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 &registry;
}

int register(something Class)
{
pair<const char *, void (something::*)()> p(typeid(Class).name(),
Class::factory);

getMap()->insert(p);
}

void *create(const char *classname)
{
FactoryMap::iterator it = getMap()->find(classname);
if(it != getMap()->end())
return it->second();
else
return NULL;
}

class A
{
public:
static A *factory(){return new A;}
};
int aDummy = register(A); // THIS IS THE SORT OF CALL I'M AFTER


class B : public A
{
public:
static A *factory(){return 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.registerFactory(&class1Factory);
factories.registerFactory(&class2Factory);

MyClass* c1= factories.create("Class1");
MyClass* c2= factories.create("Class2");


c1->dofoo();
c2->dofoo();

return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top