2010-11-25 61 views
0

Mon but est de créer un système dans lequel je peux fournir le nom de la chaîne d'une classe au moment de l'exécution et lui faire retourner une instance de cette classe à son tour. En recherchant stackoverflow, je suis tombé sur un exemple qui semble faire exactement ce que j'essaye d'accomplir, bien que je ne puisse pas le compiler correctement. Ce qui suit est basé sur ce code:Comment réparer mon motif d'usine pour éradiquer ces erreurs de compilation?

//LevelObject.h  
#pragma once 

#include <map> 
#include <string> 

class LevelObject 
{ 
    protected: 
     int ID; 

    public: 
     template<class T> static LevelObject* createT(void) 
     { 
      return new T(0); 
     } 

     LevelObject(void); 
     ~LevelObject(void); 
}; 

struct BaseFactory 
{ 
    typedef std::map<std::string, LevelObject*(*)()> map_type; 

    static LevelObject* createInstance(const std::string& s) 
    { 
     map_type::iterator it = getMap()->find(s); 
     if(it == getMap()->end()) 
     { 
      return 0; 
     } 
     return it->second(); 
    } 

    private: 
     static map_type* objectMap; 

    protected: 
     static map_type* getMap() 
     { 
      if(!objectMap) 
      { 
       objectMap= new map_type; 
      } 
      return objectMap; 
     } 
}; 

template<class T> 
struct DerivedRegister : BaseFactory 
{ 
    DerivedRegister(const std::string& s) 
    { 
     getMap()->insert(std::make_pair(s, &LevelObject::createT<T>)); 
    } 
}; 


//Item.h 
#pragma once 

#include "LevelObject.h" 

class Item : 
    public LevelObject 
{ 
    int ID; 
    static DerivedRegister<Item> reg; 

public: 
    Item(int id); 
    ~Item(void); 
}; 


//Item.cpp 
#include "Item.h" 

Item::Item(int id) 
{ 
    ID = id; 
} 

Item::~Item(void) 
{ 
} 

DerivedRegister<Item> Item::reg("item"); 

La logique est que les objets dérivés, à savoir, l'article va enregistrer une chaîne et la référence à une fonction qui renvoie une instance de lui-même. Lors de l'appel de createInstance, il prendra une chaîne entrée par l'utilisateur et utilisera la carte pour déterminer l'objet à renvoyer.

Malheureusement, ce code n'est pas compilent correctement, et me donne les erreurs suivantes:

erreur Erreur 1 C2752: 'std :: tr1 :: _ Remove_Reference < _Ty>': plus d'un partiel spécialisation correspond à la liste des arguments de modèle

erreur erreur 2 C2528: 'abstrait declarator': pointeur de référence est illégale c: \ program files \ microsoft Visual studio 10.0 \ vc \ include \ type_traits 965

Erreur 3 Erreur C2528: 'type': pointeur de référence est illégal c: \ program files \ Visual Studio Microsoft 10.0 \ vc \ include \ type_traits 349

Si quelqu'un peut aider à atténuer ces erreurs, je l'apprécierais grandement. Ou peut-être que je vais tout à fait mal à ce sujet en premier lieu, donc si quelqu'un pense plutôt que je devrais aller dans une direction différente entièrement s'il vous plaît faites le moi savoir.

Merci d'avance.

+0

Veuillez modifier le nom de la variable en autre chose. C'est déroutant en lisant le code. –

Répondre

0

I ajouté corps vides au constructeur de la classe LevelObject et destructor:

LevelObject(void) { } 
~LevelObject(void) { } 

a ensuite déclaré la variable membre map statique de la classe BaeFactory:

BaseFactory::map_type* BaseFactory::map; 

et le code compilé sans erreurs dans les deux GCC et Visual Studio.

+0

Merci pour la réponse rapide, mais en faisant ces ajustements, je suis toujours incapable de le compiler. – Brandon

+0

J'ai remarqué que sans la dernière ligne du code que j'ai posté, tout se compilera bien. Êtes-vous sûr de copier cette ligne lorsque vous testez tout? – Brandon

1

Cela fait longtemps que cette question a été postée, mais comme il n'y a pas de réponse et que je suis tombé par hasard ici aussi, je me suis dit que j'en ajouterais un. J'ai copié le même code d'usine que vous l'avez fait (à partir de la réponse StackOverflow here) et j'ai eu le même problème. J'ai trouvé la solution à this réponse StackOverflow.

Il s'avère que Visual Studio 2010 (que je suppose que vous utilisez) a un problème avec std::make_pair. Il suffit d'utiliser std::pair<std::string,LevelObject*(*)()> à la place et vous serez prêt à partir. Au moins, cela a résolu exactement le même problème pour moi.

+0

Merci de poster ceci, j'ai eu le même problème. Cela a corrigé la première erreur, maintenant j'obtiens un external non résolu: private: static std :: map , classe std :: allocateur > .... la chaîne continue. Des idées pourquoi? ces modèles me confondent sans fin, en particulier les erreurs de compilation: S –

+0

Cette deuxième erreur semble qu'il serait vraiment difficile d'essayer et de diagnostiquer sans le message complet, les échantillons de code, etc. Ma suggestion serait d'aller de l'avant et d'ouvrir un nouveau SO question à ce sujet. Qui sait, vous pourriez ne pas être le premier avec le même problème. – daveaglick

+0

Merci pour la réponse, c'était un externe non résolu concernant la collection de cartes dans l'usine. Je l'ai corrigé en ajoutant CBaseFactory :: map_type * CBaseFactory :: map = new map_type(); dans la base.cpp –