Vectors and abstract classes - c++

In SFML there are a few types of objects (sf::Shape, sf::Sprite, sf::Text) which inherit an abstract base class sf::Drawable. If I create an std::vector can I store all the objects which inherit the sf::Drawable class in that vector?

If you create a std::vector that stores some form of pointer (ideall a smart pointer) you can do it.

You cannot create objects of abstract classes, so you cannot store them in a vector. You can, however, store pointers to those objects in a vector.

yes you can if you declare a vector as
std::vector <sf::Drawable*>
any pointer on object based on this base class can be store in the vector.

If I create an std::vector can I store all the objects which inherit the sf::Drawable class in that vector?
Yes you can do that. You'll need a vector of pointers then (because you cannot instantiate abstract classes).

Related

Storing polymorphic game objects efficiently in a C++ container

For a 2D game I'm working on I have made a vector of pointers to an object. This object is the parent class where all other game objects inherit from. So the actor is such an object, items are, enemies are, etc. The class containing this vector (an object manager) executes virtual functions of this class, such as run() and draw().
For me this was just a straightforward implementation where I did not really think about at the time. Now I've come to a point where I actually have to delete objects from the container. Some quick searches on the internet tell me that a vector implementation is right for this task (using swap and pop), but also that I should store the objects themselves on the vector for even more performance. So: not pointers but the actual instances. This way they are allocated on the stack I guess. Is this even possible when using inheritance? And is there an even faster way to store inherited game objects?
Is this even possible when using inheritance?
No, it's not possible to store polymorphic objects in a container without using a pointer or a reference.
The way I would do it is with a combination of std::vector and std::unique_ptr:
template<class T> using container = std::vector<std::unique_ptr<T>>;
container<base> vector;
The pushing is made via:
vector.emplace_back(std::unique_ptr<base>(new item()));
vector.emplace_back(std::unique_ptr<base>(new enemy()));
where base is the base class and item and enemy are derived classes.

How to store a vector of objects of an abstract class which are given by std::unique_ptr?

I got a loop in which i use a function returning std::unique_ptr to an object of an abstract class. I want to store these objects into a std::vector via push_back. But since the objects are of abstract type i get the following error:
error: cannot allocate an object of abstract type
for the line
cells.push_back(std::move(*cell));
where cells is a std::vector of the abstract type and cell is of type
std::unique_ptr<AbstractType>&& cell
(I actually pass cell to a handler class)
I know that one can not instantiate an abstract type and as I'm understanding the std:move operator it need to instantiate the object somehow?
Can anybody help me how to manage the problem? Or should the function (not my part of the project) not return a unique pointer to an object of an abstract type?
You can't store AbstractType elements directly on a std::vector. You can simply store the unique_ptrs themselves in a std::vector<std::unique_ptr<AbstractType>> with cells.push_back(std::move(cell)).

C++, array of objects (from different classes) without Stl & Boost

I want to create in C++ an array which can hold objects of diffrent classes.
It's a part of my hometask and one of the conditions is that i can't use Stl, Boost & etc.
You should create Base class and derive your class from Base class. And as a result you can create array Base* array and put there all derived classes.
You could store pointers to void* in your array and cast your objects to void*. But you should not do this!
If possible you should derive all your objects from a Base Class and store pointers to Base*. This is the better way to solve this problem.
Does the same container have to hold objects of the same type at the same time? If so, does it have to be able to hold any type? If so, your only solution is to use void* and store pointers to the objects you want to store.
If one container only has to hold one type of object, then you can do this using templates. If the same container has to hold different types of objects but you can place restrictions on the types it can hold, then you can make a requirement be that it derive from some Base class, and make an array of Base*.

Adding different objects to std::list

can you add different class objects to same list?
See boost::any.
You can use std::vector and then use it to add heterogeneous types into.
Example:
std::vector<boost::any> v;
v.push_back(std::string("hello world"));
v.push_back(42);
No, if they are unrelated objects. If they are related (i.e. have a common base class) then you can store the base class pointer (use smart pointers instead of raw pointers) in the list.
Technically, you could store void * pointers to objects in your list, but generally it's not a good idea. Better use some "variant" class, such as boost::any or QVariant (if you're using Qt) that will wrap your elements.
Only if you derive the objects from the same base class and declare the list of base class type.

C++ collection of abstract base classes

how can I create STL collection of classes which implement abstract base class using the base class as collection value, without using pointers?
is there something in Boost that allows me to implement it? The collection specifically is map.
Thanks
You cannot avoid pointers completely. You must store pointers in the collection if you want to avoid Object slicing. Boost has a container that hides the pointers pretty well: ptr_map
The Boost Pointer Container Library does what you want.
You can't
Think about how the compiler would generate code to do that ?
No pointers means that the storage has to be allocated "in the collection itself" in a static array or something. But the storage required for the subclasses can change ! So how would the compiler do it ? ... it can't ...