Domanda

Memorizzazione di oggetti in un vettore eterogeneo con oggetti allocati in pila

Ciao,

Supponiamo che io abbia una classe astratta CA, derivata in CA1, CA2 e forse altre.

Voglio mettere oggetti di questi tipi derivati ??in un vettore, che ho inserito in un CB di classe. Per ottenere il polimorfismo giusto, devo memorizzare un vettore di puntatori:

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

Ora, supponiamo che io abbia la seguente funzione principale:

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

Come posso scrivere il metodo void CB :: Store (const CA & amp;) in modo semplice, così gli oggetti memorizzati sopravvivono quando gli oggetti originali vengono distrutti (cosa che non si verifica nel semplice esempio sopra).

Il mio problema è che devo prima copiare gli oggetti nell'heap prima di copiare il loro indirizzo nel vettore, ma come posso creare un oggetto di un tipo derivato? Certo, potrei usare RTTI e cercare tutti i tipi possibili, creare e allocare un puntatore e copiare (con il casting adeguato) l'oggetto nello spazio allocato prima di spingerlo nel vettore. Ma questo sembra abbastanza complicato, no?

C'è un modo più semplice?

(E senza usare l'allocazione dinamica in generale!)

È stato utile?

Soluzione

Comunemente, fornirai una funzione clone: ??

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);
    }
}

Questo si chiama costruttore virtuale , puoi costruire copie di oggetti in fase di esecuzione:

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

Dovresti prendere in considerazione l'uso del Boost.Pointer Container biblioteca. Il tuo codice sarebbe:

boost::ptr_vector<CA> objects;

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

E ora non hai più bisogno di gestire la memoria da solo. La libreria rispetta anche le funzioni di clonazione e la chiamerà quando si eseguono copie dei propri oggetti. Tutorial qui .

Altri suggerimenti

Sembra che tu abbia bisogno di una funzione clone () nella tua classe astratta che le tue classi derivate implementeranno.

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

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

Una possibilità sarebbe quella di modellare Store sul tipo di argomento:

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

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

Un avvertimento: a differenza di " clone () " soluzione pubblicata da altri, questa è soggetta ad affettare. Ad esempio, questo funziona bene:

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

Ma questo non:

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

Dare una copia protetta ctor a CA impedisce tale uso improprio. Tuttavia, se subclassiamo ulteriormente la sottoclasse CA1, il problema ritorna.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top