2010-07-09 25 views
6

Ich brauche eine Reihe von Datenpunkten in Form von (namen, value) zu speichern, wobei der Wert verschiedene Arten nehmen könnte.C++ Wie ein heterogenen Container erstellen

Ich versuche, eine Klassenvorlage für jeden Datenpunkt zu verwenden. Dann möchte ich für jeden Datenpunkt, den ich sehe, ein neues Objekt erstellen und es zurück in einen Vektor schieben. Für jeden neuen Typ muss ich zuerst eine neue Klasse aus der Vorlage erstellen. Aber ich kann die Objekte in keinem Vektor speichern, da Vektoren für alle Einträge den gleichen Typ erwarten. Die Typen, die ich speichern muss, können nicht in eine Vererbungshierarchie eingefügt werden. Sie sind nicht verwandt. Außerdem können in Zukunft weitere Typen erstellt werden, und ich möchte den Speicherdienst nicht für jeden neuen Typ ändern. Gibt es eine Möglichkeit, einen heterogenen Container zum Speichern dieser Einträge zu erstellen? Vielen Dank!

+0

Es zeigt eine Möglichkeit, mit der Laufzeit-Polymorphismus des Umgangs. Ich denke, es ist verwandt. https://youtu.be/vxv74Mjt9_0?t=16m8s –

+0

Mögliches Duplikat von [Wie kann ich Objekte unterschiedlichen Typs in einem C++ Container speichern?] (Https://stackoverflow.com/questions/4738405/how-can- i-store-Objekte-von-unterschiedlichen-Typen-in-ac-container) –

Antwort

7

Die Boost-Bibliothek hat wahrscheinlich das, was Sie für (boost :: any) suchen. Sie können Ihre eigenen mit einem eingewickelten Zeiger Ansatz rollen, wenn Sie nicht Boost verwenden können ...

+1

Danke! Ich denke "Any" wird funktionieren! Ich habe auch ein Tutorial dazu auf boost :: any gefunden. Hier ist es, wenn jemand das braucht! http://www.devx.com/cplus/10MinuteSolution/29757/1954 – Abhi

0

Ich dachte, dass Sie nur ein Paar (Typ, void *) und schreiben Sie Ihre eigene Pop-Funktion, die den void * abhängig auf den Typ in dem Paar beschreiben und dann schieben Sie diese in was auch immer Behälter Ihr Auge fällt.

+0

wie von Neil erwähnt, fehleranfällig und ineffizient, würde ich auch nicht empfehlen. Entweder Neil Vorschlag folgen und nur Vererbung oder einen Blick auf boost :: any nehmen wie von 6502. – cjh

4

Das Problem mit Containern wie diesem ist, dass wenn Sie auf etwas im Container zugreifen möchten, müssen Sie seinen Typ bestimmen und dann irgendwie auf den tatsächlichen Typ umwandeln. Das ist hässlich, ineffizient und fehleranfällig, weshalb die erste Wahl in C++ die Vererbung ist, es sei denn, Sie haben einen sehr guten Grund, dies nicht zu tun - etwas, auf das ich in meiner C++ - Karriere nie gestoßen bin.

+0

Dank Neil zuvor erwähnte! ... Also diese Datentypen sind im Grunde alle über den Ort, sie sind eine Reihe von Knöpfen, wenn Sie mögen . Sie können long int, string, bool und so weiter sein :(Vererbung kann nicht verwendet werden. – Abhi

+1

Das Problem mit Vektoren und C++ - Klassen ist, dass Sie keinen Vektor von Base deklarieren können und dann Instanzen von Derived in den Code setzen. Wegen Kopie Philosophie von C++ eine solche Implementierung für std :: vector (oder jede andere std :: Container) Zeiger verwenden muss (schließlich gewickelt sind). – 6502

+1

@Abhi Eigentlich können Sie die Vererbung verwenden, das ist, wie boost :: alle Werke, es löscht der Typ in eine private Basis, die einen Template-abgeleiteten Typ hat, der die Werte enthält, dies ist alles versteckt in boost :: any, wo sein Konstruktor/Zuweisungsoperator den Typ löscht (sie sind Templates). Jedoch schlage ich vor, dass du dein Design überlegst, Sie dies wirklich brauchen. –

9

boost::any wurde bereits empfohlen, aber es ist für alles, so dass Sie nicht viel davon erwarten können.

Wenn Sie die verschiedenen Typen im Voraus kennen, verwenden Sie besser .

typedef boost::variant<Foo, Bar, Joe> variant_type; 

struct Print: boost::static_visitor<> 
{ 
    void operator()(Foo const& f) const { f.print(std::cout); } 

    template <class T> 
    void operator()(T const& t) const { std::cout << t << '\n'; } 
}; 

void func(variant_type const& v) // not template 
{ 
    boost::apply_visitor(Print(), v); // compile-time checking 
            // that all types are handled 
}