2010-09-27 5 views
0

Je dois stocker des références aux instances de classes dérivées en C++. J'ai considéré utiliser un vecteur de shared_ptrs à la classe de base (car il doit contenir différents types de classes dérivées), cependant, il est important que le conteneur contienne les pointeurs d'origine, ce qui n'est pas le cas avec les vecteurs (ou autres conteneurs stl), si je ne me trompe pas. Y at-il un moyen de le faire en C++ natif, ou dois-je utiliser des conteneurs spéciaux comme ptr_vector de Boost?C++: conteneur de pointeurs d'origine

EDIT: Ceci est mon code de test:

class Foo 
{ 
public: 
    Foo() {} 
    virtual ~Foo() {} 
    virtual void set_x(int i) = 0; 
}; 

class Bar : public Foo 
{ 
public: 
    Bar() {} 

    void set_x(int i) 
    { 
     this->x = i; 
    } 

    int x; 
}; 

int main() 
{ 
    Bar bar; 

    // ptr 
    std::cout << &bar << "\n"; 

    std::vector<Foo*> foos; 
    foos.push_back(&bar); 

    // different ptr value 
    std::cout << &foos[0] << "\n"; 

    foos[0]->set_x(1); 

    // however, changes are made 
    std::cout << bar.x; 

    return 0; 
} 

Merci à l'avance,

jena

+0

Est-ce que le vecteur (un vecteur de pointeurs vers vos objets) ne fonctionnerait pas pour vous? – JoshD

+0

il n'est pas clair pour moi pourquoi un conteneur de 'shared_ptr' ne fonctionnera pas pour vous. –

+0

J'ai essayé cela, mais quand j'ajoute le pointeur d'une instance via vector.push_back (& ​​instance), le pointeur dans le vecteur diffère de celui d'origine. – jena

Répondre

1

Dans votre exemple ci-dessus, vous imprimez l'adresse du pointeur et non la valeur du pointeur.

Au lieu de:

// different ptr value 
std::cout << &foos[0] << "\n"; 

Do

// different ptr value 
std::cout << foos[0] << "\n"; 

Mis à part que votre vector<Foo*> fonctionnera très bien.

+0

C'est déprimant ... Vous avez raison, bien sûr. Merci d'avoir signalé cela, je devrais vraiment envisager de dormir. Merci à tous pour votre aide - je m'excuse pour cette vacuité. – jena

+0

Je suis content que je puisse vous aider. Si c'était une bonne solution, pourriez-vous la marquer comme la réponse acceptée? – JoshD

0

Si vous utilisez shared_ptr comme membre du conteneur, le pointeur dans chaque membre conserve l'accès à l'instance d'objet d'origine. Vous pouvez obtenir une copie d'un shared_ptr à tout moment après l'entretien du conteneur, mais l'objet d'origine sera toujours sa cible. Pour une solution plus simple, vous pouvez utiliser boost::ptr_vector, à condition qu'aucun de vos pointeurs n'apparaisse deux fois dans le conteneur - ce scénario introduirait une complexité complexe de gestion des ressources et vous ramènerait à shared_ptr.

+0

Est-ce que shared_ptr a du sens avec les types qui ne sont pas alloués sur le tas? – jena

+0

Non. Dans ce cas, lorsque la variable est hors de portée, votre 'shared_ptr' pointera vers le junk sur la pile, peut-être même la mémoire inaccessible après stackframe unwind. –

1

Vous pouvez créer un fichier std :: vector < toto *, qui contiendra tous les pointeurs vers foo que vous lui avez donnés. Il ne fera pas essayer de supprimer ces pointeurs sur la destruction, ce qui peut être ou ne pas être ce que vous voulez, mais il contiendra exactement les valeurs que vous passez.

Vous pouvez également créer un std :: vector < shared_ptr < toto>>, qui contiendra les pointeurs qui seront libérés une fois qu'il n'y aura plus de copies pendantes du shared_ptr flottant. Ceux-ci contiendront aussi le "original" foo * que vous avez passé; vous pouvez l'obtenir à nouveau en utilisant la méthode shared_ptr :: get(). La seule fois où vous ne verriez pas exactement le même pointeur que votre objet dérivé, c'est si vous utilisez plusieurs héritages de classes et que vos classes de base incluent des données. Parce qu'un foo * finirait, dans ce cas, en pointant sur la partie "foo" des données, qui ne serait pas nécessairement à la "racine" de l'objet.

+0

Je n'utilise pas l'héritage multiple, mais la classe de base contient des données. Serait-ce la raison pour laquelle les éléments du vecteur ont des pointeurs différents des originaux? – jena

+0

Vous n'avez pas vu votre exemple la première fois; l'autre réponse a déjà atteint la cible de votre problème, à savoir que vous receviez l'adresse des données VECTOR et non le pointeur lui-même. Le sommeil est une partie importante du développement. :) – SomeCallMeTim