2010-09-21 6 views
2

J'ai deux classes: une classe Object et une classe ObjectManager. La classe ObjectManager stocke "Objects" via un conteneur ptr_vector. Dans certains cas, j'ai besoin de récupérer des références à ces pointeurs stockés pour effectuer des actions individuelles sur ceux-ci. Comment ferais-je cela?Comment récupérer une référence à partir d'un boost ptr_vector?

compilable Pseudo Code:

#include <boost/ptr_container/ptr_vector.hpp> 
#include <boost/shared_ptr.hpp> 

class Object 
{ 
public: 
    int m_Id; 
    Object(int id) : m_Id(id) { } 
}; 

class ObjectManager 
{ 
private: 
    typedef boost::shared_ptr<Object> ObjectPtr; 
    typedef boost::ptr_vector<Object> ObjectVectorPtr; 
    typedef ObjectVectorPtr::iterator ObjectIt; 

    ObjectVectorPtr vector_; 

    void AddObject(Object *obj) { 
    vector_.push_back(obj); 
    } 

    ObjectPtr FindObject(int id) { 
    for (ObjectIt it = vector_.begin(); it != vector_.end(); it++) { 
     if (it->m_Id == id) { 
     // Found the object...How to return a shared_ptr reference to it? 
     // The line below is invalid, obviously: 
     // cannot convert parameter 1 from 'Object' to 'const boost::shared_ptr<T> &' 
     return *it; 
     } 
    } 

    // We could not find anything. 
    return ObjectPtr(); 
    } 
}; 

Fondamentalement, je veux le ObjectManager de conserver la propriété, mais je veux également d'autres classes pour être en mesure d'obtenir une référence à l'objet, les méthodes d'appel d'utilisation sur cet objet en fonction de ce qui est passe, et continue.

Répondre

2

Convertir votre conteneur à utiliser shared_ptr comme membre:

#include <boost/ptr_container/ptr_vector.hpp> 
#include <boost/shared_ptr.hpp> 
#include <vector> 

class Object 
{ 
public: 
    int m_Id; 
    Object(int id) : m_Id(id) { } 
}; 

class ObjectManager 
{ 
private: 
    typedef boost::shared_ptr<Object> ObjectPtr; 
    typedef std::vector<ObjectPtr> ObjectVectorPtr; 
    typedef ObjectVectorPtr::iterator ObjectIt; 

    ObjectVectorPtr vector_; 

    void AddObject(ObjectPtr& obj) { 
    vector_.push_back(obj); 
    } 

    ObjectPtr FindObject(int id) { 
    for (ObjectIt it = vector_.begin(); it != vector_.end(); ++it) { 
     if (it->get()->m_Id == id) { 
     // Found the object - return a shared_ptr reference to it 
     return ObjectPtr(*it); 
     } 
    } 

    // We could not find anything. 
    return ObjectPtr(); 
    } 
}; 

BTW - préfèrent ++it vs it++ pour éviter la construction supplémentaire et n'utilisez pas ce type de correspondance si le conteneur devient grand - passez à std::map<int, ObjectPtr> avec m_id comme clé ou std::set aveccorrectement définifonction.

Si j'étais super-pédant, je suggère de remplacer votre boucle de trouver avec un appel à std::find_if, avec un prédicat qui correspond à Object::m_id ...

+0

Ahh, merci Steve! De plus, si cela ne vous dérange pas de répondre, lorsque vous dites «n'utilisez pas ce type de correspondance si le conteneur devient grand», faites-vous référence à des problèmes de performance? – jbaez

+0

@jbaez: oui ceci est lié à un perf - l'appariement comme ceci sera O (n) - la recherche de la carte (arbre binaire) est O (log n) –

0

Vous ne pouvez pas renvoyer de shared_ptr car l'objet n'a pas été créé initialement en tant qu'objet partagé - quel serait le nombre de références?

Vous pouvez cependant retourner un objet * assez facilement:

Object* FindObject(int id) { 
    for (ObjectIt it = vector_.begin(); it != vector_.end(); it++) { 
     if (it->m_Id == id) { 
     // Found the object...How to return a shared_ptr reference to it? 
     // The line below is invalid, obviously: 
     // cannot convert parameter 1 from 'Object' to 'const boost::shared_ptr<T> &' 
     return &*it; 
     } 
    }