views:

985

answers:

3

Hi,

Let's say I have an stl vector containing class type "xx". xx is abstract. I have run into the issue where the compiler won't let me "instantiate" when i do something like the following:

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

void main()
{
    ;
}

I assume this is because the copy constructor must be called. I have gotten around this issue by storing xx*'s in the vector rather than xx's. Is there a better solution? What is it?

+11  A: 

When you use push_back, you are making a copy of the object and storing it in the vector. As you surmised, this doesn't work since you can't instantiate an abstract class, which is basically what the copy-construction is doing.

Using a pointer is recommended, or one of the many smart-pointer types available in libraries like boost and loki.

Steve Guidi
But *don't* use std::auto_ptr. Those cannot be put into STL containers because of their strange copy semantics.
Tyler McHenry
You could also use boost's ptr_vector - http://www.boost.org/doc/libs/1_39_0/libs/ptr_container/doc/ptr_container.html
bdonlan
just to clarify, when using stl vector you are basically copying the state of xx and then when you retrieve it, c++ will first instantiate xx and then fill it with appropriate properties? As opposed to just pointing at the old object. So the whole issue is we end up using xx's constructor?
Ori Cohen
If xx is a type (and not a pointer), then when you create a `vector<xx>`, it copies the xx objects into the vector using the xx copy constructor. If the xx type has a properly-written copy constructor (or is simple enough that the default copy constructor is sufficient), then this equates to creating a new xx inside the vector that has the same internal state as the old xx. This is not strictly the same as creating a new xx and *then* filling it with the state of the old xx (that would use the default constructor and the assignment operator), but the difference is subtle.
Tyler McHenry
A: 

std::vector (and the whole STL in general) is designed to store values. If you have an abstract class, you don't intent to manipulate value of this type, but to manipulate pointer or references to it. So have a std::vector of abstract class doesn't make sense. And even if it isn't abstract, it doesn't usually make sense to manipulate class designed to be base classes as value, they usually should be noncopiable (copy constructor and assignment operator declared private and not implemented is the standard trick, inheriting from a suitable class whose lone purpose is to make its descendant non copiable -- boost::noncopyable for instance -- has become fashionanle).

AProgrammer
+1  A: 

To be more Catholic than the Pope (or in this case Steve Guidi) the requirements for objects stored in STL containers are that they are copy-constructable and assignable and an abstract class is neither. So in this case a container of pointers is the way to go. Another thing to consider in case you decide to fix things by not making the class abstract would be slicing.

Eugen Constantin Dinca