2010-06-27 3 views
3

J'utilise ptr_map de boost pour stocker des objets dérivés d'un type abstrait de base.ptr_map et pointeur

class Entity { virtual void foo() = 0; }; 
class Entity1 : public Entity {}; 
class Entity2 : public Entity {}; 

boost::ptr_map<string, Entity> someMap; // We could store pointers for abstract type 

Insertion fonctionne très bien:

someMap.insert("someKey", new Entity1()); 
someMap.insert("someKey", new Entity2()); 

Mais pas le retour de la carte:

template<typename EntityType> 
EntityType *GetEntity(const string &entityName) 
{ 
    return dynamic_cast<EntityType*>(&someMap[entityName]); 
} 

GetEntity<Entity1>(entityName); 

Maintenant le problème: opérateur [] de référence ptr_map retourne! Ainsi, dans constructur, il peut y avoir appel de type à partir de la valeur. Maintenant compilateur échoue avec l'erreur:

instantiated from ‘EntityType* EntityManager::GetEntity(const std::string&) [with EntityType = Entity1, std::string = std::basic_string<char>]’ 
error: cannot allocate an object of abstract type ‘Entity’ 

S'il y a une méthode qui retourne dans ptr_map pointeur sur la valeur, il woudln't y avoir aucun problème. Que pourriez-vous dire à ce sujet?

Répondre

4

Un fait souvent oublié est que l'opérateur [] va instancier la clé si elle n'existe pas. C'est un problème dans votre cas car la clé est abstraite. Donc, à la place, utilisez at(). C'est,

return dynamic_cast<EntityType*>(&someMap.at(entityName)); 

Pour plus d'informations, consultez la section "Semantics: lookup"

BTW, je mets en doute votre décision de conception afin d'exposer des pointeurs premières stockées dans le conteneur dont l'objet est d'alléger la gestion de la mémoire.

+0

probablement vous voulez dire: l'opérateur [] instanciera la valeur/l'objet, pas la clé. De plus, la clé n'est pas abstraite ici. –