EDIT: minor fixes (virtual Print; return mpInstance) following remarks in the answers.
I am trying to create a system in which I can derive a Child class from any Base class, and its implementation should replace the implementation of the base class.
All the objects that create and use the base class objects shouldn't change the way they create or call an object, i.e. should continue calling BaseClass.Create() even when they actually create a Child class. The Base classes know that they can be overridden, but they do not know the concrete classes that override them.
And I want the registration of all the the Child classes to be done just in one place.
Here is my implementation:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
template<typename Class>
class CRegisteredClassFactory: public CAbstractFactory
{
public:
~CRegisteredClassFactory(){};
Class* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
Class* pClass;
};
// holds info about all the classes that were registered to be overridden
class CRegisteredClasses
{
public:
bool find(const string & sClassName);
CAbstractFactory* GetFactory(const string & sClassName)
{
return mRegisteredClasses[sClassName];
}
void RegisterClass(const string & sClassName, CAbstractFactory* pConcreteFactory);
private:
map<string, CAbstractFactory* > mRegisteredClasses;
};
// Here I hold the data about all the registered classes. I hold statically one object of this class.
// in this example I register a class CChildClass, which will override the implementation of CBaseClass,
// and a class CFooChildClass which will override CFooBaseClass
class RegistrationData
{
public:
void RegisterAll()
{
mRegisteredClasses.RegisterClass("CBaseClass", & mChildClassFactory);
mRegisteredClasses.RegisterClass("CFooBaseClass", & mFooChildClassFactory);
};
CRegisteredClasses* GetRegisteredClasses(){return &mRegisteredClasses;};
private:
CRegisteredClasses mRegisteredClasses;
CRegisteredClassFactory<CChildClass> mChildClassFactory;
CRegisteredClassFactory<CFooChildClass> mFooChildClassFactory;
};
static RegistrationData StaticRegistrationData;
// and here are the base class and the child class
// in the implementation of CBaseClass::Create I check, whether it should be overridden by another class.
class CBaseClass
{
public:
static CBaseClass* Create()
{
CRegisteredClasses* pRegisteredClasses = StaticRegistrationData.GetRegisteredClasses();
if (pRegisteredClasses->find("CBaseClass"))
{
CRegisteredClassFactory<CBaseClass>* pFac =
dynamic_cast<CRegisteredClassFactory<CBaseClass>* >(pRegisteredClasses->GetFactory("CBaseClass"));
mpInstance = pFac->CreateAndGet();
}
else
{
mpInstance = new CBaseClass;
}
return mpInstance;
}
virtual void Print(){cout << "Base" << endl;};
private:
static CBaseClass* mpInstance;
};
class CChildClass : public CBaseClass
{
public:
void Print(){cout << "Child" << endl;};
private:
};
Using this implementation, when I am doing this from some other class:
StaticRegistrationData.RegisterAll();
CBaseClass* b = CBaseClass::Create();
b.Print();
I expect to get "Child" in the output.
What do you think of this design? Did I complicate things too much and it can be done easier? And is it OK that I create a template that inherits from an abstract class?
I had to use dynamic_pointer (didn't compile otherwise) - is it a hint that something is wrong?
Thank you.