C++ Résumé de l'Usine à l'aide de modèles
Je suis en train de créer un résumé de l'usine modèle pour plusieurs abstraite des usines en C++ et est venu avec cette.
#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;
}
Il compile et fonctionne très bien avec pas de fuites de mémoire (win32 crtdbg) mais je ne sais pas si c'est vraiment la bonne façon de faire un résumé de l'usine modèle.
temp.Register("DA", (Creator<Base>*)new DerivedCreator<DerivedA>);
Je suis également s'interroger sur la ligne ci-dessus. Je ne comprends pas pourquoi j'ai à lancer. Je ne comprends pas des modèles très bien, mais je suppose que cela devrait fonctionner correctement considérant qu'à la fois le modèle de la classe et de la classe réelle sont dérivés.
Que le code fonctionne correctement, comme indiqué ci-dessus et même supprime fine avec pas de fuites de mémoire. Je ne me sens pas entièrement à l'aise avec elle.
Je n'ai pas été en mesure de trouver des exemples réels de modèle de classes, à l'exception de Mangues (wow émulateur) - https://mangos.svn.sourceforge.net/svnroot/mangos/trunk/src/framework/Dynamic/ObjectRegistry.h
Mais je ne pense pas que je peux utiliser cette méthode dans mon projet car j'ai l'intention sur l'utilisation de la Dll à un certain point dans mon projet et il utilise PFI qui est contre mon exigence pour polymorphisme d'exécution.
Bien ce que je suis en train de faire est de créer une 3 partie intégrante de la solution. Au programme, de la Bibliothèque, et DLL. La DLL contient la mise en œuvre, La Bibliothèque contient de l'usine, et le programme utilise l'interface. Le modèle existe parce que je vais en faire beaucoup. Je l'utilise pour remplacer mon moteur de jeu de la sélection du pilote. Actuellement, il a copié/collé le code de la Vidéo, de la Physique, de la Saisie et de l'Audio.
OriginalL'auteur NtscCobalt | 2010-12-05
Vous devez vous connecter pour publier un commentaire.
La classe
DerivedCreator<DerivedA>
est unCreator<DerivedA>
pas unCreator<Base>
.Vous devez dire à la dérivée du modèle de ce que le type de base de sorte qu'il peut mettre en œuvre l'interface de
Creator<Base>
par la création d'une instance du type dérivé:OriginalL'auteur Pete Kirkham
Petites remarques pour améliorer la conception :
1) Utiliser shared_ptr au lieu de raw pointeurs
2) utiliser std::string à la place de char*
Vous avez à jeter, parce que les types de Créateur, Créateur et le Créateur< DerivedB > sont complètement différents types. La manière de résoudre les qui est de supprimer les conversions :
shared_ptr
est une assez mauvaise idée. Non seulement vous risquez d'obtenir des références circulaires, et les fuites de mémoire, c'est aussi de loin le plus lent sorte de pointeur intelligent. L'utilisation des pointeurs intelligents, oui. Mais seulement d'utilisershared_ptr
en particulier lorsque vous avez absolument besoin de la propriété partagée.Oui j'ai certainement d'accord que le passage de la char* est une bonne idée. Constaté que l'un la manière dure, quand j'ai appelé pBase = temp.Créer("DA"); à partir d'un espace d'adressage séparé de la fonction registre. Je ne prévoyez sur l'utilisation des pointeurs intelligents, mais que je suis meilleur de programmation simple sans eux, je vais donc ajouter plus tard.
OriginalL'auteur BЈовић
Vous pouvez faire de l'Usine::Enregistrer un modèle de méthode et d'utiliser boost mpl affirmer à l'intérieur de
reinterpret_cast
est jeté le résultat en arrière à l'original, donc à utiliserFunctionMap
vous devez connaître les types spécifiques du créateur que vous obtenez à partir d'elle, ce qui n'est pas une option viable.Vous n'avez pas à jeter en arrière, car affirmer garantit que _Base est dérivé de la (ou des) T type, le compilateur permet de s'assurer Fn points de Créateur<"quel que soit"> type de.
OriginalL'auteur TomK