What about class factories?
Base::Create would handle an internal class factory collection of duh!, class factory objects. :D
1 2 3 4 5
|
class IClassFactory
{
public:
Base& Create(int arg) = 0;
};
| |
Then each derived class would have to provide its own class factory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
class Derived : public Base
{
class _Factory : public IClassFactory
{
public:
Base& Create(int arg)
{
return *(new Derived(int));
}
};
static _Factory _myFactory;
....
public:
static IClassFactory* GetFactory() { return &_myFactory; }
}
| |
Now, there is still one more thing you need to define: How to identify the class factory the caller of Base::Create wants to be used. COM uses GUID's (and a more complex class factory mechanism). You could use typeid() and RTTI and use the returned typeid to index factories in a std::map collection, which also forces us to modify the original signature of Create():
1 2 3 4 5 6
|
class Base
{
....
static Base& Create(int typeID, int arg);
static std::map<int, IClassFactory*> _factories;
};
| |
At this point you need to decide how to fill in the _factories collection. I think I would use a C array and I would construct it statically.
1 2 3 4 5 6 7 8 9 10
|
class Base
{
....
static std::pair<int, IClassFactory*> __initFactories[];
static std::map<int, IClassFactory*> _factories;
};
std::pair<int, IClassFactory*> Base::__initFactories[] = { std::pair(typeid(Derived), Derived::GetFactory()), std::pair(typeid(Derived2), Derived2::GetFactory()), ... };
std::map<int, IClassFactory*> Base::_factories(__initFactories, __initFactories + _countof(__initFactories));
| |
And I think that does it. Now you can do:
Derived d = dynamic_cast<Derived&>Base::Create(typeid(Derived), someArg);
None of the above is tested, but hopefully you get the idea.
Personally though, I think this is a hard way of doing it (now that I have finished pouring the idea out). Since I am bound to identify the type with RTTI and typeid, what is my gain when compared to the templated way?