I\'m refactoring a single 3000+-line class with a tangled web of conditionals and switches into a set of worker classes. Previously part of the constructor would select whic
I would suggest creating a common base class (if you've not already got one) and then using a factory class to encapsulate the creation process. The factory would just return a pointer to your base class which has the prototype run method.
Something along these lines:
class Type
{
virtual void Run() = 0;
};
class TypeFoo : public Type
{
public:
TypeFoo() {};
virtual void Run() {};
static Type* Create() { return new TypeFoo(); };
};
class TypeBar : public Type
{
public:
TypeBar() {};
virtual void Run() {};
static Type* Create() { return new TypeBar(); };
};
class TypeBaz : public Type
{
public:
TypeBaz() {};
virtual void Run() {};
static Type* Create() { return new TypeBaz(); };
};
class TypeFactory
{
typedef Type* (*CreateFn)();
public:
static Type* RandomTypeFooWeighted()
{
CreateFn create[] =
{
TypeFoo::Create,
TypeFoo::Create, // weighted towards FOO
TypeBar::Create,
TypeBaz::Create
};
const int fncount = sizeof(create)/sizeof(*create);
return create[ rand()%fncount ]();
}
};
So to use it you can just call:
Type *t = TypeFactory::RandomTypeFooWeighted();
Credit to Nawaz for the function pointer bits and bobs.
The answer is : a base class and an array of function pointers can help you do that.
struct Base { virtual ~Base() {} }; //make ~Base() virtual
struct Foo : Base {};
struct Bar : Base {};
struct Baz : Base {};
template<typename T>
Base *Create() { return new T(); }
typedef Base* (*CreateFn)();
CreateFn create[] =
{
&Create<Foo>,
&Create<Foo>, // weighted towards FOO
&Create<Bar>,
&Create<Baz>
};
const size_t fncount = sizeof(create)/sizeof(*create);
Base *Create()
{
return create[rand() % fncount](); //forward the call
}
Then use it as (ideone demo):
int main() {
Base *obj = Create();
//work with obj using the common interface in Base
delete obj; //ok,
//the virtual ~Base() lets you do it
//in a well-defined way
return 0;
}