Question

Stockage d'objets dans un vecteur hétérogène avec des objets alloués à la pile

Bonjour,

Dites que j'ai une classe abstraite CA, dérivée de CA1, CA2 et peut-être d'autres.

Je souhaite placer des objets de ces types dérivés dans un vecteur, que j'ai intégré dans une classe CB. Pour que le polymorphisme fonctionne correctement, je dois stocker un vecteur de pointeurs:

class CB
{
    std::vector <CA*> v;
};

Maintenant, supposons que j’ai la fonction principale suivante:

int main()
{
    CB b;
    CA1 a1;
    CA2 a2;
    b.Store( a1 );
    b.Store( a2 );
}

Comment écrire la méthode void CB :: Store (const CA & amp;) de manière simple, afin que les objets stockés survivent lorsque les objets d'origine sont détruits (ce qui ne se produit pas exemple simple ci-dessus).

Mon problème est que je dois d'abord copier des objets sur le tas avant de copier leur adresse dans le vecteur, mais comment puis-je créer un objet d'un type dérivé? Bien sûr, je pouvais utiliser RTTI et rechercher tous les types possibles, créer et allouer un pointeur et copier (avec la transposition appropriée) l'objet dans l'espace alloué avant de le pousser dans le vecteur. Mais cela semble assez compliqué, non?

Existe-t-il un moyen plus simple?

(Et sans utiliser l'allocation dynamique en général!)

Était-ce utile?

La solution

Généralement, vous allez fournir une fonction de clonage:

struct CA
{
    virtual CA *clone(void) const = 0;
    virtual ~CA() {} // And so on for base classes.
}

struct CA1 : public CA
{
    virtual CA *clone(void) const
    {
        return new CA1(*this);
    }
}

struct CA2 : public CA
{
    virtual CA *clone(void) const
    {
        return new CA2(*this);
    }
}

Ceci s'appelle un constructeur virtuel , vous pouvez construire des copies d'objets au moment de l'exécution:

void CB::Store(const CA& pObject)
{
    CA *cloned = pObject.clone();
}

Vous devriez envisager d'utiliser le Boost.Pointer Container bibliothèque. Votre code serait:

boost::ptr_vector<CA> objects;

void CB::Store(const CA& pObject)
{
    objects.push_back(pObject->clone());
}

Et maintenant, vous n'avez plus besoin de gérer la mémoire vous-même. La bibliothèque respecte également les fonctions de clonage et l'appellera lors de la copie de vos objets. Tutoriel ici .

Autres conseils

On dirait que vous avez besoin d'une fonction clone () dans votre classe abstraite que vos classes dérivées implémenteront.

class CA
{
   public:
   virtual ~CA() {}
   virtual CA* clone() const = 0;
}

class CA1 : public CA
{ 
    public:
    virtual CA *clone() const
    {
       return new CA1(*this);
    }
};

Une possibilité serait de modéliser Store sur le type de son argument:

class CB
{
public:
    template<class T>
    void Store(const T& t)
    {
         v.push_back(new T(t));
    }

private:
    std::vector <CA*> v;
};

Un avertissement cependant: contrairement à " clone () " solution affichée par d’autres, elle est sujette au découpage en tranches. Par exemple, cela fonctionne bien:

CB b;
CA1 a1;
CA2 a2;
b.Store(a1);
b.Store(a2);

Mais cela ne veut pas:

CA1 a1;
CA* a = &a1;
b.Store(*a); //Ouch! this creates a new CA, not a CA1

Attribuer un certificat de copie protégée à l'autorité de certification empêche une telle utilisation abusive. Cependant, si nous approfondissons la sous-classe CA1, le problème revient.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top