Frage

Speichern von Objekten in heterogenen Vektor mit Stapel zugewiesenen Objekte

Hallo,

Sagen, ich habe eine abstrakte Klasse CA, abgeleitet in CA1, CA2, und vielleicht andere.

Ich möchte Objekte dieser abgeleiteten Typen in einen Vektor setzen, dass ich in eine Klasse CB embbed. Um Polymorphismus richtig, ich brauche einen Vektor von Zeigern zu speichern:

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

Nun, sagen, ich habe die folgende Hauptfunktion:

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

Wie schreibe ich die Methode void CB::Store(const CA&) auf einfache Art und Weise, so dass die gespeicherten Objekte überleben, wenn die ursprünglichen Objekte zerstört werden (die in dem einfachen Beispiel tritt nicht oben).

Mein Problem ist, dass ich auf dem Heap erste Kopie Objekte müssen, bevor sie ihre Adresse in den Vektor zu kopieren, aber wie kann ich ein Objekt einer abgeleiteten Typ erstellen? Sicher, ich könnte RTTI verwenden und für alle möglichen Arten suchen, erstellen und einen Zeiger zuweisen, und kopiere (mit dem richtigen Casting) das Objekt in den zugewiesenen Raum, bevor es in den Vektor schieben. Aber das scheint ziemlich kompliziert, nicht wahr?

Gibt es einen einfacheren Weg?

(Und ohne dynamische Zuordnung in der Haupt!)

War es hilfreich?

Lösung

Im Allgemeinen werden Sie eine Klon-Funktion bieten:

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

Dies ist ein virtuellen Konstruktor , können Sie konstruieren Kopien von Objekten zur Laufzeit:

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

sollten Sie die Verwendung von Boost.Pointer Container Bibliothek. Ihr Code wäre:

boost::ptr_vector<CA> objects;

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

Und jetzt haben Sie keine Notwendigkeit, Speicher selbst zu verwalten. Die Bibliothek achtet auch Klon-Funktionen und wird es nennen, wenn Kopien der Objekte machen. Tutorial hier .

Andere Tipps

Klingt wie Sie eine Klon () Funktion in Ihrer abstrakten Klasse benötigen, die Ihre abgeleiteten Klassen implementieren werden.

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

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

Eine Möglichkeit wäre Store templatize von der Art ihres Arguments:

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

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

Eine Warnung aber: Im Gegensatz zu dem „Klon ()“ Lösung von anderen geschrieben, dies ist anfällig für Slicing. Zum Beispiel funktioniert das gut:

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

Aber das bedeutet nicht:

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

eine geschützte Kopie Ctor CA Giving verhindert einen solchen Missbrauch. Wenn wir jedoch weiter CA1 Unterklasse, die Frage kommt zurück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top