Estoy tratando de crear una plantilla de fábrica abstracta para varias fábricas abstractas en C++ y se me ocurrió esto.C++ Abstract Factory usando plantillas
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <map>
#include <stdio.h>
class Base
{
public:
virtual ~Base() {}
virtual bool Get() = 0;
};
class DerivedA : public Base
{
public:
bool Get()
{
return true;
}
};
class DerivedB : public Base
{
public:
bool Get()
{
return false;
}
};
template <class T>
class Creator
{
public:
virtual ~Creator(){}
virtual T* Create() = 0;
};
template <class T>
class DerivedCreator : public Creator<T>
{
public:
T* Create()
{
return new T;
}
};
template <class T, class Key>
class Factory
{
public:
void Register(Key Id, Creator<T>* Fn)
{
FunctionMap[Id] = Fn;
}
T* Create(Key Id)
{
return FunctionMap[Id]->Create();
}
~Factory()
{
std::map<Key, Creator<T>*>::iterator i = FunctionMap.begin();
while (i != FunctionMap.end())
{
delete (*i).second;
++i;
}
}
private:
std::map<Key, Creator<T>*> FunctionMap;
};
int main(int argc, char** argv[])
{
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
//Register
Factory<Base, char*> temp;
temp.Register("DA", (Creator<Base>*)new DerivedCreator<DerivedA>);
temp.Register("DB", (Creator<Base>*)new DerivedCreator<DerivedB>);
//Pointer to base interface
Base* pBase = 0;
//Create and call
pBase = temp.Create("DA");
printf("DerivedA %u\n", pBase->Get());
delete pBase;
//Create and call
pBase = temp.Create("DB");
printf("DerivedB %u\n", pBase->Get());
delete pBase;
return 0;
}
Se compila y funciona muy bien sin pérdidas de memoria (win32 crtdbg), pero no sé si esto es realmente la forma correcta de hacer una plantilla de la fábrica abstracta.
temp.Register("DA", (Creator<Base>*)new DerivedCreator<DerivedA>);
También me pregunto acerca de la línea anterior. Estoy confundido por qué tengo que lanzar. No entiendo las plantillas muy bien, pero supongo que debería funcionar bien teniendo en cuenta que tanto la clase de plantilla como la clase real se derivan.
Ese código realmente funciona bien como se muestra arriba e incluso elimina bien sin pérdidas de memoria. Simplemente no me siento del todo cómodo con eso.
no he podido encontrar ejemplos reales de clases de plantilla a excepción de esto desde mangos (WOW emulador) - https://mangos.svn.sourceforge.net/svnroot/mangos/trunk/src/framework/Dynamic/ObjectRegistry.h
Pero no creo que pueda usar ese método en mi proyecto porque pienso sobre el uso de archivos DLL en algún momento de mi proyecto y utiliza CRTP que va en contra de mi requerimiento de polimorfismo en tiempo de ejecución.
Sí, la línea informados es malo. No hay relación entre los dos tipos. Están especializados para diferentes tipos. Tampoco estoy seguro de por qué te molestas con CRTP en absoluto. Por lo general, se usa para * evitar * funciones virtuales. Pero todavía tienes esos, ¿por qué molestarse con las plantillas? – jalf
Bueno, lo que intento hacer es crear una solución de 3 partes. Programa, biblioteca y DLL. La DLL contendrá la implementación, The Library contiene la fábrica y el programa usa la interfaz. La plantilla existe porque voy a estar haciendo esto mucho. Lo estoy usando para reemplazar la selección de controladores de mi motor de juego actual. Actualmente tiene un código de copia/pegado para video, física, entrada y audio. – NtscCobalt