2009-08-10 4 views
3

Angenommen, ich habe einen STL-Vektor, der den Klassentyp "xx" enthält. xx ist abstrakt. Ich habe in der Frage führen, wo der Compiler lässt mich nicht „instanziiert“ wenn ich etwas wie das folgende tun:stl vector.push_back() abstrakte Klasse kompiliert nicht

std::vector<xx> victor; 
void pusher(xx& thing) 
{ 
    victor.push_back(thing); 
} 

void main() 
{ 
    ; 
} 

Ich nehme an, das liegt daran, dass der Copy-Konstruktor muss aufgerufen werden. Ich habe dieses Problem gelöst, indem ich xx * im Vektor statt xx gespeichert habe. Gibt es eine bessere Lösung? Was ist es?

Antwort

12

Wenn Sie push_back verwenden, erstellen Sie eine Kopie des Objekts und speichern es im Vektor. Wie Sie vermutet haben, funktioniert das nicht, da Sie eine abstrakte Klasse nicht instanziieren können, was im Grunde die Kopierkonstruktion ist.

Es wird empfohlen, einen Zeiger oder einen der vielen Smart-Pointer-Typen zu verwenden, die in Bibliotheken wie boost und loki verfügbar sind.

+7

Aber * nicht * std :: auto_ptr. Diese können aufgrund ihrer seltsamen Kopiesemantik nicht in STL-Container eingegeben werden. –

+5

Sie könnten auch Boost's ptr_vector - http://www.boost.org/doc/libs/1_39_0/libs/ptr_container/doc/ptr_container.html – bdonlan

+1

verwenden, um nur zu verdeutlichen, dass Sie bei der Verwendung von stl-Vektor grundsätzlich den Zustand von xx kopieren und dann, wenn Sie es abrufen, instanziiert C++ zuerst xx und füllt es dann mit entsprechenden Eigenschaften? Anstatt nur auf das alte Objekt zu zeigen. Das ganze Problem ist, dass wir am Ende den Konstruktor von xx verwenden. – Ori

0

std :: vector (und die gesamte STL im Allgemeinen) wurde entwickelt, um Werte zu speichern. Wenn Sie eine abstrakte Klasse haben, möchten Sie den Wert dieses Typs nicht manipulieren, sondern den Zeiger oder Verweise darauf ändern. Also hat ein std :: Vektor der abstrakten Klasse keinen Sinn. Und selbst wenn es nicht abstrakt ist, macht es normalerweise keinen Sinn, Klassen zu bearbeiten, die als Basisklassen als Wert definiert sind, sie sollten normalerweise nicht kopierbar sein (Kopierkonstruktor und Zuweisungsoperator sind privat deklariert und nicht implementiert ist der Standardtrick, der von eine geeignete Klasse, deren einziger Zweck darin besteht, ihren Nachkomme nicht kopierbar zu machen - zum Beispiel boost :: nicht kopierbar - ist zu Modeanle geworden).

2

Um katholischer zu sein als der Papst (oder in diesem Fall Steve Guidi) sind die Anforderungen an Objekte, die in STL-Containern gespeichert sind, dass sie kopierfähig und zuweisbar sind und eine abstrakte Klasse auch nicht. Also in diesem Fall ist ein Container mit Zeigern der richtige Weg. Eine andere Sache zu berücksichtigen, falls Sie sich entscheiden, Dinge zu beheben, indem Sie nicht die Klasse Zusammenfassung wäre slicing.