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.
Related
Simply written I would like to ask "what is a good reason to use smart pointers?"
for ex std::unique_ptr
However, I am not asking for reasons to use smart pointers over regular (dumb) pointers. I think every body knows that or a quick search can find the reason.
What I am asking is a comparison of these two cases:
Given a class (or a struct) named MyObject use
std:queue<std::unique_ptr<MyObject>>queue;
rather than
std:queue<MyObject> queue;
(it can be any container, not necessarily a queue)
Why should someone use option 1 rather than 2?
That is actually a good question.
There are a few reasons I can think of:
Polymorphism works only with references and pointers, not with value types. So if you want to hold derived objects in a container you can't have std::queue<MyObject>. One options is unique_ptr, another is reference_wrapper
the contained objects are referenced (*) from outside of the container. Depending on the container, the elements it holds can move, invalidating previous references to it. For instance std::vector::insert or the move of the container itself. In this case std::unique_ptr<MyObject> assures that the reference is valid, regardless of what the container does with it (ofc, as long as the unique_ptr is alive).
In the following example in Objects you can add a bunch of objects in a queue. However two of those objects can be special and you can access those two at any time.
struct MyObject { MyObject(int); };
struct Objects
{
std::queue<std::unique_ptr<MyObject>> all_objects_;
MyObject* special_object_ = nullptr;
MyObject* secondary_special_object_ = nullptr;
void AddObject(int i)
{
all_objects_.emplace(std::make_unique<MyObject>(i));
}
void AddSpecialObject(int i)
{
auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
special_object_ = emplaced.get();
}
void AddSecondarySpecialObject(int i)
{
auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
secondary_special_object_ = emplaced.get();
}
};
(*) I use "reference" here with its english meaning, not the C++ type. Any way to refer to an object (e.g. via a raw pointer)
Usecase: You want to store something in a std::vector with constant indices, while at the same time being able to remove objects from that vector.
If you use pointers, you can delete a pointed to object and set vector[i] = nullptr, (and also check for it later) which is something you cannot do when storing objects themselves. If you'd store Objects you would have to keep the instance in the vector and use a flag bool valid or something, because if you'd delete an object from a vector all indices after that object's index change by -1.
Note: As mentioned in a comment to this answer, the same can be archieved using std::optional, if you have access to C++17 or later.
The first declaration generates a container with pointer elements and the second one generates pure objects.
Here are some benefits of using pointers over objects:
They allow you to create dynamically sized data structures.
They allow you to manipulate memory directly (such as when packing or
unpacking data from hardware devices.)
They allow object references(function or data objects)
They allow you to manipulate an object(through an API) without needing to know the details of the object(other than the API.)
(raw) pointers are usually well matched to CPU registers, which makes dereferencing a value via a pointer efficient. (C++ “smart” pointers are more complicated data objects.)
Also, polymorphism is considered as one of the important features of Object-Oriented Programming.
In C++ polymorphism is mainly divided into two types:
Compile-time Polymorphism
This type of polymorphism is achieved by function overloading or operator overloading.
Runtime Polymorphism
This type of polymorphism is achieved by Function Overriding which if we want to use the base class to use these functions, it is necessary to use pointers instead of objects.
I have two class, one for storing base data, and the other for storing additional data as following:
struct AnimationState(){
virtual ~ AnimationState(){};
Vector3f m_spacialData;
float m_fTimeStamp;
}
And the derived class:
struct HermiteAnimationState() : public AnimationState{
virtual ~HermiteAnimationState(){};
Vector3f m_tangentIn;
Vector3f m_tangentOut;
}
My question: is how can I, at first, create an instance of HermiteAnimationState, and then upcast it to AnimationState for storing in a vector like this:
std::vector<AnimationState> m_vStates;
...
Lately, I can get the object AnimationState and downcast it to HermiteAnimationState for accessing the additional data (member m_tangentIn and m_tangentOut).
HermiteAnimationState* p = dynamic_cast<HermiteAnimationState*>(&m_vStates[i])
The way polymorphism works in C++ is that if B is a base class and D is derived from B, then:
a pointer to D can be used where a pointer to B is expected
a reference to D can be used where a reference to B is expected
What you can't do in C++ is actually use a value of type D in a context where a value of type B is expected. For example, you can't store derived objects in an array of base object. This makes sense when you consider that a derived object may have a different size from a base object.
Similarly, you can't store derived objects in a vector of base objects.
What you can do is store pointers to HermiteAnimationState in a vector of pointers to AnimationState. It's up to you how to manage the memory. For example, the following would be valid:
std::vector<AnimationState*> m_vStates;
HermiteAnimationState h_a_s;
m_vStates.push_back(&h_a_s);
...
HermiteAnimationState* p = dynamic_cast<HermiteAnimationState*>(m_vStates[i])
Since h_a_s is a local variable, it'll be destroyed automatically at the end of its scope.
But this is probably an unworkable approach, because you probably want the objects referred to by the vector elements to persist beyond the current scope. We can use std::unique_ptr for this purpose. A std::unique_ptr owns the object it points to, and as long as it stays alive, so does that object; and it deletes the object when it is itself destroyed. So a vector of std::unique_ptr objects behaves like a vector of objects themselves in terms of memory management. Now you can do
std::vector<std::unique_ptr<AnimationState*>> m_vStates;
m_vStates.emplace_back(new HermiteAnimationState);
...
HermiteAnimationState* p =
dynamic_cast<HermiteAnimationState*>(m_vStates[i].get());
(Note, however, that you can't copy this vector; you can only move it.)
Basically, you need to use some kind of reference to the pointed object because you need dynamic polymorphism.
The simplest but error-prone would be using "naked" pointers. The first thing that is problematic with this is that you have to do the destroying manually: containers will destroy the pointer, not what is pointed.
The safer way to do this is to use smart pointers, which are designed to do the destruction depending on a pre-fixed rule that the smart pointer embedd in it's type. The simplest one and certainly the best choice if you are doubting is std::unique_ptr, which can't be copied but can be moved. The other choice, which should be thought carefully about before being used, is the std::shared_ptr which is useful IFF you don't know when you should destroy these objects but you know it's when some systems will refer no more to it. Some other systems might just be observing that object, in which case std::weak_ptr.
Now, from reading your question, I think you are certainly processing a lot of these animation data. There is an obvious design issue there, I think, I might be wrong.
However, it looks like, if you have a lot of these AnimationState to manage, in a loop, you will get performance issues. This is common issues in games, mainly caused by "cache conherency".
What I would recommand in this case, would be to NOT use
inheritance: it's an invitation to the cpu to jump all over the place and trigger cache misses;
dynamic_cast: it's one of the few operations that are not guaranteed to end in a predictable time (with new and delete for example), which basically mean that if you are in a critical loop, you can lose a lot of time through it. In some cases, you can't avoid using dynamic cast (like when doing dynamic plugins), but in most cases, using it just because you have chosen to use inheritance is just wrong. If you use inheritance, then you should use virtual calls.
However, what I suggest is even more drastic: don't use inheritance at all.
Obviously, this is only an advice. If you are not doing something with a critical loop, it doesn't matter. I'm just worried because it looks like you are doing some inheritance for composition, which always have bad consequences both on readability of the code and performance.
See this example.
an University class has a Director and many student So my class will be like this
a)
class University {
Director d;
Student list[1000];
};
or
b)
class University {
Director* d;
Student* list[1000];
};
My problem is how to decide whether class attributes should be pointer or value.
Most all other answers focus on the detail of heap vs. direct containment (or provide no information at all, like use pointers when you want pointers... Rather than focusing on the details, consider the overall design of the application.
The first question would be about ownership. In your program, are those students and director owned by the class? Or do they exist outside of the class scope. In most simple applications, the objects might only exist inside the class, but in other more complex designs, the students might belong to the school, and only be referenced in the class (or the director might also teach some courses to other classes). If the class owns the objects, the composition will be the best approach: hold the director directly as a member, and the students inside a container that is directly held by the class (I would recommend a vector, which is the safe choice for most cases).
If the objects don't belong to the class, then you will rather use aggregation. Whoever owns the object will have to manage the lifetimes and decide how to store the real objects and the class would only hold references (in the general sense) to those objects. Things get more complicated as there are more choices. If ownership can be transferred, then you would dynamically allocate the objects and hold pointers, where you should read smart pointers so that memory will be managed for you.
If ownership does not change and the lifetime of the students/director are guaranteed to extend beyond the lifetime of the class, you could use references. In particular for the director. In the case of the students, it will be more complex as you cannot have containers of plain references, so the solution might still be pointers there, a vector of pointers. Another issue with references is that they cannot be reseated, which means that if you hold a reference to the director, the director of the class will be fixed for the whole lifetime of the class and you won't be able to replace her.
Design is somehow complicated and you will learn with experience, but hopefully this will provide a quick start onto your problem.
The issue here is: Where is the storage for these member variables? Sometimes it makes sense that a piece of data was allocated somewhere else and used other places. In that case a pointer may make sense (rather than using a copy constructor). However, usually that isn't the case (especially with encapsulation). Then you want to store the member data in the class. In such a case, and your example looks like it is, you don't want to use a pointer.
how to decide whether class attributes should be pointer or value
I would mostly go for value (i.e. object). In some special cases, I will choose a pointer (may be a smart one!). For your case, below would suffice:
class University {
Director d;
std::vector<Student> list;
public:
University () { list.reserve(1000); }
};
The advantage of having an object is that you don't have to do your own garbage collection as the resource management will be automatic.
Pointers can be used, when you want to change the ownership of the resource (similar to shallow copy), at the same time avoiding expensive copies created during copy c-tor or assignment. In all other cases, use objects (i.e. value) for composition.
Well it depends. Pointers should be used when you want to add stuff to the heap, while this means you have a bit more freedom in when/how you allocate memory, you have to add more code to avoid memory leaks: ie destructors and deleting stuff. It also allows you to easily modify the values from other functions/classes without having to pass a reference, just pass it in its pointer form.
One obvious situation when pointers are totally needed is in a binary tree node object, since it must contain objects of the same type as itself, it must use pointers to those objects. IE:
struct Node{
Node* left;
Node* right;
//Other stuff
};
In many situations however, its up to your own discretion. Just be responsible for your pointers if you use them.
Actually there are three options
1. Object
2. Reference
3. Pointer
It's part of the design/architect .. on what to use for what object.
Mostly .. the deciding criteria will be, lifecycles of the objects and the containers.
In both cases the class attributes are being stored by value, it just happens that in the second case those values are pointers.
Use pointers when you want pointers, use non-pointers when you don't want pointers. This entirely depends on the desired semantics of the class that you are writing.
This is what i would go for:
class University {
Director d;
Student **list;
};
Even though its much of a personal matter. i think using pointer to pointer is better in this case if you know what you are playing with!
I dont think a pointer array is a good choice. If you dont want pointers then use Value
I'd like to manage a bunch of objects of classes derived from a shared interface class in a common container.
To illustrate the problem, let's say I'm building a game which will contain different actors. Let's call the interface IActor and derive Enemy and Civilian from it.
Now, the idea is to have my game main loop be able to do this:
// somewhere during init
std::vector<IActor> ActorList;
Enemy EvilGuy;
Civilian CoolGuy;
ActorList.push_back(EvilGuy);
ActorList.push_back(CoolGuy);
and
// main loop
while(!done) {
BOOST_FOREACH(IActor CurrentActor, ActorList) {
CurrentActor.Update();
CurrentActor.Draw();
}
}
... or something along those lines. This example obviously won't work but that is pretty much the reason I'm asking here.
I'd like to know: What would be the best, safest, highest-level way to manage those objects in a common heterogeneous container? I know about a variety of approaches (Boost::Any, void*, handler class with boost::shared_ptr, Boost.Pointer Container, dynamic_cast) but I can't decide which would be the way to go here.
Also I'd like to emphasize that I want to stay away as far as possible from manual memory management or nested pointers.
Help much appreciated :).
To solve the problem which you have mentioned, although you are going in right direction, but you are doing it the wrong way. This is what you would need to do
Define a base class (which you are already doing) with virtual functions which would be overridden by derived classes Enemy and Civilian in your case.
You need to choose a proper container with will store your object. You have taken a std::vector<IActor> which is not a good choice because
Firstly when you are adding objects to the vector it is leading to object slicing. This means that only the IActor part of Enemy or Civilian is being stored instead of the whole object.
Secondly you need to call functions depending on the type of the object (virtual functions), which can only happen if you use pointers.
Both of the reason above point to the fact that you need to use a container which can contain pointers, something like std::vector<IActor*> . But a better choice would be to use container of smart pointers which will save you from memory management headaches. You can use any of the smart pointers depending upon your need (but not auto_ptr)
This is what your code would look like
// somewhere during init
std::vector<some_smart_ptr<IActor> > ActorList;
ActorList.push_back(some_smart_ptr(new Enemy()));
ActorList.push_back(some_smart_ptr(new Civilian()));
and
// main loop
while(!done)
{
BOOST_FOREACH(some_smart_ptr<IActor> CurrentActor, ActorList)
{
CurrentActor->Update();
CurrentActor->Draw();
}
}
Which is pretty much similar to your original code except for smart pointers part
My instant reaction is that you should store smart pointers in the container, and make sure the base class defines enough (pure) virtual methods that you never need to dynamic_cast back to the derived class.
As you have guessed you need to store the objects as pointers.
I prefer to use the boost pointer containers (rather than a normal container of smart pointers).
The reason for this is the boost ptr container access the objects as if they were objects (returning references) rather than pointers. This makes it easier to use standard functors and algorithms on the containers.
The disadvantage of smart pointers is that you are sharing ownership.
This is not what you really want. You want ownership to be in a single place (in this case the container).
boost::ptr_vector<IActor> ActorList;
ActorList.push_back(new Enemy());
ActorList.push_back(new Civilian());
and
std::for_each(ActorList.begin(),
ActorList.end(),
std::mem_fun_ref(&IActor::updateDraw));
If you want the container to exclusively own the elements in it, use a Boost pointer container: they're designed for that job. Otherwise, use a container of shared_ptr<IActor> (and of course use them properly, meaning that everyone who needs to share ownership uses shared_ptr).
In both cases, make sure that the destructor of IActor is virtual.
void* requires you to do manual memory management, so that's out. Boost.Any is overkill when the types are related by inheritance - standard polymorphism does the job.
Whether you need dynamic_cast or not is an orthogonal issue - if the users of the container only need the IActor interface, and you either (a) make all the functions of the interface virtual, or else (b) use the non-virtual interface idiom, then you don't need dynamic_cast. If the users of the container know that some of the IActor objects are "really" civilians, and want to make use of things which are in the Civilian interface but not IActor, then you will need casts (or a redesign).
ok, so I got a doubt, I want to know if this is possible:
I'm using a database, with generic data (strings, ints, bools, etc...). Whenever an object is constructed or a member of an object is modified, I have to query the database with the specific action (SELECT or UPDATE).
First of all, this isn't a DB related question, my real problem is that I have a ptr_vector which holds boost::any's pointers to members of the object. In code something like this:
class Enemy{
private:
//some private data...
public:
auto_ptr<int> ID_Enemy;
auto_ptr<string> Enemy_Name;
//miscellaneous methods...
};
then I pass the members I want to modify to a function of another miscellaneous class which takes as argument a boost::any*:
misc_class.addValues((boost::any*)(ID_Enemy.get()));
misc_class.addValues((boost::any*)(Enemy_Name.get()));
that same class accepts the any*, and does the following:
auto_ptr<boost::any> val2(val); //being val, the passed any*
Enemy_Values.push_back(val2);
Enemy_Values is a ptr_vector. So when I access this misc_class which has Enemy_Values as member, I want to change the value to which an auto_ptr inside is pointing:
misc_class.Enemy_Values[0] = (boost::any)(69);
And here, I get a violation error. I've tried many things, and someone told me that I shouldn't be using containers of auto_ptr or converting back and forth with boost::any. Is this that I am doing possible, or there is a better and more intuitive way?
Thanks in advance.
(boost::any*)(ID_Enemy.get()) performs a reinterpret_cast since you are casting unrelated pointer types. This means you get an invalid pointer to an any, pointing to what is really an integer.
Instead, construct a temporary boost::any object and pass it by reference to addValues:
misc_class.addValues(boost::any(ID_Enemy.get());
Your use of auto_ptr is in fact incorrect: auto_ptr deletes objects on the freestore but here we're dealing with locals instead. addValues merely needs to push the value of the any object into the vector:
Enemy_Values.push_back(val);
... and Enemy_Values should just be a std::vector.
You could do this with a ptr_vector and freestore-allocated boost::any objects, but that would be more complicated than necessary.
auto_ptr has a number of problems. Since you are already using boost, why not use boost::shared_ptr instead?