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

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*.

Related

Vectors and abstract classes

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).

How to create an array in which the type is abstract but the objects will be derived classes (C++)

my issue is that i need to be able to create an array of 100 objects. However the objects could be one of four different objects all of which are ultimately derived from an abstract class. I could use 4 separate arrays but it appears as if my teacher only wants us to use one array.
Class structure is : DVD & VHS are derived from Video, CD & Cassette are derived from Audio, Audio & Video are derived from Media. Audio, Video, and Media are all abstract.
You'll have to use pointers. You can't copy or assign derived types, at least not through a declaration of the base type.
for an array
- the size of type must be known (for reserving the contigous memory)
- the type may not be an abstract class (for initializing the class must be instantiable)
the only solution for an array is to use pointer indirection, as the size of a pointer is known. you can use raw or smart pointers to base class. when using raw pointers you have to take care of the object destruction before deleting the array. when your array itself resides on the heap do not forget delete [].
to overcome these issues a standard container like vector should be used with a smart pointer. only then a simple deletion of the container deletes all the media objects. if the container shall reside on the heap you should as well use a smart pointer to hold it.
make yourself familiar with these two concepts. and if you have no idea what types are best use vector and shared_ptr until you know better.
forgot to say: vector you find in the standard library, shared_ptr you find ther only in a C++11 compiler. if you have an older compiler you have to include boost libraries.

dynamic_cast reference to base class in stl container

Is it possible to store a bunch of objects by their base class in say an std::list without pointers. I would really like the objects to be held in the container, then retrieve a pointer to the object in the container and dynamic_cast it to correct derived class.
I have it working fine using pointers. Like (super simple version):
class IComponent
{
virtual ~Icomponent(){}
}
class PositionComponent: public IComponent
{
//...
float x, y;
}
std::list<IComponent*> CList;
//...
// fill the list
// put reference to object in pComponent
//...
PositionComponent* position = dynamic_cast<PositionComponent*>( pComponent)
position->x = 346452.235612;
But the memory management is a huge pain. My actual structure is a
map<enumValue, map<int, IComponent*> >
I get the feeling I can't use the objects themselves because when I add any derived component into the list the extra data will be cut off and leave me with the base class only. This didn't figure this until I tried static_cast instead and it crashed.
Can answer my original question and/or confirm my feelings on the matter. Thanks!
to minimize pain of manual memory management use smart pointers: std::unique_ptr if your compiler already supports it or boost::shared_ptr, but not std::auto_ptr that is not supposed to be used in containers
As you guessed, when you stored an object in a container by value, it gets sliced and the data is chopped off.
If you only need to store one data type (you only show one in your code), then you can make the container hold that type.
If not, you really are stuck using pointers. You can make the memory management much easier by using a smart pointer, or if appropriate, a boost ptr_container of some sort.
Further you might want to think if you need to spend one more iteration considering your design to provide an interface that doesn't require doing a dynamic_cast to get the original type back out again.
Is it possible to store a bunch of objects by their base class in say
an std::list without pointers.
This sentence seems to be contrdicted in C++ point of view IMO. Because STL container can only hold same type of object, if you put derived object into a base type container, it got sliced.
So the apparent normal solution is to use container to hold base type pointers like you did(u could use boost/std smart pointer for memory management)
If you really want to store different objects in one STL container, you may want to consider use boost::any.

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 ...