I'm using box2d and as you already may know, it holds a void* to an object which i can use as reference when collisions occur between different entities. Problem is that the original item is saved inside a shared_ptr since the ownership is unknown and different classes (example player class) can 'equip' another class (weapon).
I'm just wondering if its possible to put this pointer inside a shared_ptr and refer to the same object as the original one?
This is an example:
std::vector<std::shared_ptr<Environment>> listEnvironment;
listEnvironment.push_back(std::make_shared(new Weapon()));
//takes a void pointer
box2d->userId = listEnvironment.back().get();
//some shit happens somewhere else and collision occurs and I get pointer back from box2d's callback:
Environment* envPtr = static_cast<Environment*>(box2d->userId);
As you can see envPtr is going to cause trouble.
Is there a way to refer to the old smart-pointer and increase its reference value?
PS:
In actuality every class creates an box2d body which holds a 'this' pointer so i don't actually have the address to the smart-pointer either. The example above is kind narrowed down to give you a hint of the problem i'm facing.
Best regards
nilo
If Environment has std::enable_shared_from_this<Environment> as a parent class then, yes. Just call envPtr->shared_from_this().
Related
Okay, so my situation is really complex to a relativity new person to C++ like me. I'm making a game (AGK library) and I have a framework class that is the base class for all of the game's objects to have standard functions like frameEvent and such that are to be overwritten by the child object.
That's all fine and dandy, and I've gotten about 70% through development, but I ran across one vital problem.
To make life easier while processing the game, each object that is a part of the game is just a pointer in a vector of type Framework*. Framework being the base class. I was told that making it a pointer allows me to have child objects of different types as long as they're a pointer as well. So far it's worked out.
Every frame, the global object runs through the vector of all the objects and runs their
frameEvent
frameEndEvent -- Can't be overriden
drawEvent
They're really just functions. So in the enemy's bullet class, I need to check if it collides with oPlayer, so I have a functions in the global class (The global class is passed to the objects in their frame event so they can communicate with other objects.) that grabs a given object.
It searches through all of the objects to find the parameter object -- so if I pass new oPlayer, it will return the real oPlayer pointer in the game.
When the bullet collides with the player, it needs to lower the player's health and then destroy itself. So at the create function for the bullet, it creates a dummy player then locates the real one using the global class function. The code is
//Find the player
oPlayer* tempPlayer = new oPlayer;
playerChecker = ObjGlobal->classToObject(tempPlayer);
tempPlayer->objectDestroy();
That code works, but it needs playerChecker to be type Framework* because that's what classToObject returns. But when I later use that pointer, I can't access the player's members even though that's the player's pointer.
playerChecker->hitPoints--;
hitPoints is exclusive to oPlayer. I think it's called object splicing or slicing, but I thought that's what using pointers fixed.
So I tried to make playerChecker type oPlayer*, but it says that Framework* can't be converted to it. So I have no idea what to do.
Any help is greatly appreciated.
Your Framework* from classToObject can be downcast to a oPlayer* using a dynamic_cast, like so:
oPlayer* playerChecker = dynamic_cast<oPlayer*>(ObjGlobal->classToObject(tempPlayer));
if (oPlayer) {
// cast succeeded, do stuff with the pointer
}
dynamic_cast is a C++ type cast operator just like the C-style cast, with some special properties. It is specifically designed to convert between pointers or references to polymorphic objects (like your oPlayer, which can be treated as both a Framework and an oPlayer). It also adds a run-time check which verifies that the object you're trying to downcast is indeed an instance of the class you're trying to cast to. If it isn't, it will return a null pointer, or in the case of references, throw an exception.
Your code will also work with a C-style cast or a static_cast (which is much like a C-style cast with compile-type type checking).
static_cast<oPlayer*>(ObjGlobal->classToObject(tempPlayer)) // static_cast
(oPlayer*)ObjGlobal->classToObject(tempPlayer) // C-style cast
These have less overhead because of the lack of a run-time check, but that also means that they are unsafe unless you can guarantee that the pointer you're casting points to an object of the correct type. Also, since dynamic_cast has a very specific use, it makes it clear what your intent is.
What's the error you're getting? Please post this, as we can't offer much help otherwise.
If I had to guess, you forgot to add public: to your class FrameWork. This, or you don't have setters/getters in your class.
I have a simple question that I am not 100% sure on.
Let us say I have a Entity class, that handles objects on the screen. Let us say the Entity class has two float variables, 'x' and 'y' (aka coordinates). Also let us say the entity I am passing has already been declared and is in memory.
I have another class that handles camera movement. It requires an entity to center on. The entity that it is centered on can changed, so I need to use a pointer here I believe. The only thing I do here is grab the X and Y variables when needed. Nothing is changed here.
I've defined it as
void StarField::ChangeFollowEntity(Entity* newFollowEntity) {
followEntity = newFollowEntity;
}
where followEntity is also an Entity class. I would call ChangeFollowEntity(..) to change the entity. Is this actually correct?
I've also seen however this:
void StarField::ChangeFollowEntity(Entity newFollowEntity) {
followEntity = &newFollowEntity;
}
In both cases followEntity is defined as Entity* followEntity; .. What does the second example exactly do here? From what I understand, & would typically be used as a reference type. Maybe it is incorrect to do to begin with.
I am pretty sure I shouldn't be using a reference in this case because the followEntity changes, which references I believe cannot change and must be defined.
So my question is, is my first example correct and the right way to do it? What does the second example do exactly?
In your second version ::
void StarField::ChangeFollowEntity(Entity newFollowEntity) {
followEntity = &newFollowEntity;
}
You pass the newFollowEntity by value, so when your function is called from main or from where ever! A copy of the object is made (using the copy constructor) and sent to the function ChangeFollowEntity, and after the completion of the execution of the function, your followEntity has the address of the COPY of the object, which gets destroyed after the completion of the function call, so your pointer followEntity is left dangling, which is undefined behavior if you access any entity using the followEntity
First is the correct way to do it!!
The second example does the following:
When the function is called a new Entity object newFollowEntiry
is created and whatever is passed into the function is used to
construct it
Then an address of that local stack based object is taken and
assigned to followEntiry to be stored presumably.
When the function execution is complete newFollowEntiry is destroyed
The folowEntity pointer is now pointing at a location in stack where
there is not Entity object anymore.
BUG
What does the second example exactly do here?
Your second example creates a Entity newFollowEntity which only exists for the duration of that function call.
The address of that variable is stored, and then the variable is destroyed, leaving a dangling pointer.
That's bad.
I am pretty sure I shouldn't be using a reference in this case because the followEntity changes, which references I believe cannot change
You can use a reference in this case. A referenced object can be changed - you are probably recalling that a reference cannot be reassigned.
Edit
I suppose the code below would assume I have an overloaded version of addChild() that accepts a Sprite already wrapped in a unique_ptr, where taking ownership would be fine. Just thought I'd mention that before someone else did. :) . I made up all the code here after a very long day, so please take it as pseudo code quality meant only to demonstrate the issue at hand.
Original Question
I'm writing a framework where there is a display list, parents/children etc. I'm thinking that using unique_ptr<Sprite> for example is the way to go here, since when you add a child to a parent display object, it's only logical that the parent now becomes the sole owner of that child.
However, there will be methods available such as getChildAt(index) and getChildByName, etc, which I believe should return a reference or pointer value, since these methods are simply meant to expose a child to operations, not transfer ownership.
Finally, the issue and the reason for this question, is in the following situation. Lets assume we have two Sprite objects which are children of the root of display list, Stage. Let's say we have a third child Sprite.
Stage newStage;
std::unique_ptr<Sprite> parentOne(new Sprite);
std::unique_ptr<Sprite> parentTwo(new Sprite);
newStage.addChild(parentOne); //Stage takes ownership of parentOne
newStage.addChild(parentTwo); //Stage takes ownership of parentTwo
std::unique_ptr<Sprite> someChild(new Sprite);
parentOne->addChild(someChild) //parentOne takes ownership of someChild.
Now, somewhere else lets say in the code base of the game or whatever using this framework, someChild is accessed via getChildAt(int index);.
Sprite& child = parentOne->getChildAt(0);
It would be perfectly legal for the following to then happen.
parentTwo->addChild(child);
The addChild method handles removing the child from it's previous parent, if a parent exists, so that the new parent can now make this child part of its section of the display list.
I'm returning the child(ren) from each sprite as a reference or pointer, because we don't want to hand off ownership (in methods such as getChildAt()), just provide access to the child. We don't want to hand it off as a unique_ptr and have it fall out of scope and die.
However, as I say, it would be perfectly legal and normal for this child (now accessed by a reference or pointer) to be passed off to another container (lets say in a drag and drop operation, dragging an item from one list to another). The problem we have now is that the unique ownership needs to be transferred from one parent to another, but we only have a reference or raw pointer.
I'm wondering what a sane solution to this problem would be. If I return a pointer, is it possible to transfer the ownership correctly at this stage?
void Sprite::addChild(Sprite* newChildToOwn)
{
/* by checking newChildToOwn->parent we can see that the child is already owned
by someone else. We need to not only remove the child from that parents' part of the
display list and add it here, but transfer exclusive object ownership of newChildToOwn
to this->.
*/
}
The release method gets you the pointer to the object and releases it from the unique_ptr
http://en.cppreference.com/w/cpp/memory/unique_ptr/release
For your structure, you should probably have method called releaseChild(index) that handles you the ownership by returning pointer.
To transfer ownership you need to have access to the unique_ptr as the raw pointer knows nothing of how it is being used.
Would it work to have the remove child method return the unique_ptr so that the object is kept alive during the transfer and the Sprite will be able to take the ownership? This will allow references to be used in other places as you have already.
I have a case in my application where I need to create a new object dynamically based on what type info I get back from an external source. Basically, I have class A that handles this task. The class will either create class B, C, or D, etc. (say B is the base and C and D are derived types). Then I want to pass this object to an existing interface that is full of methods that expect a reference parameter of type B. Eventually this dynamically allocated object is stored in a boost::shared_ptr member object of another class (I use the reset() method on the shared_ptr). So at that point the memory is being managed by someone.
Basically it seems like this is bad design to me (that I'm passing this dynamically allocated object all over the place, dereferencing it at one point and then getting the pointer to it again later). On the other hand, I don't want to change several methods of an interface to take a pointer rather than a reference. I would like to leave that interface alone and dereference the pointer when I'm passing the object on to the interface for further processing. I read somewhere that when you have a method that takes a reference parameter, you're saying "I'm not concerned about memory management here" and "this object will be initialized - i.e. can't be NULL". The object was originally created on the heap though and will eventually be "owned" by another class that will manage its memory. Is still OK to have these interface methods take reference parameters in this case?
I think that the primary goal of design in terms of object usage and lifetime should be that the ownership of the object is clear and well-understood at all times. The creation and deletion is ideally handled in only one place, or is clearly signposted when you are creating and handing-off somewhere else - again, that should be done only in one place.
My preference would be that until the object is owned outright by some piece of code, then pointers should be used. Once it is owned, then the owner can pass it on as a reference.
With pointers, it's okay to interpret as "here's an object - does anyone want it?"
With references, you're saying "here's MY object - you can use it"
But if that forces you to makes the rest of your code ugly and confusing, then maintaining that ideal is not worth the price you pay. If you can at least make the creation and hand-off look clean, then you can hide the quirky stuff in some other (well-documented) part of the code...
B * myInst = A::BFactory( current_state_of_universe );
bool bSubmitted = SubmitForMagic( myInst );
if( !bSubmitted ) delete myInst;
In my game there are a lot of object of class Foo that interact with each other. A static method of the class Foo update all the object, using a container in order to track the created objects.
My problem is that a Foo object could kill another object, other instances of Foo don't know about this horrible event and they could use the dead object (deleted) anyway, thus giving an error.
I have some ideas to avoid pointer to deleted object, but I don't think they are suitable.
1) A kind of smart pointer that checks for null object.
probably this is the worse idea, I didn't not see anywhere something like this. I could create a pointer which, when delete is called, delete the pointed Foo object and then gives false when converted to Boolean (so it's possible to know if it's possible to call method on it).
2) Each Foo object doesn't track other object with a pointer but with an ID.
then the object gets a pointer to another Foo object with a static method of Foo class ( as I said Foo class has a container that tracks all the instances).
It would work also in a multithreaded environment with simple modifications, but it may be really expansive, each object searches another one in the container during each frame.
3) Each Foo object tracks objects that have a pointer to it.
The object, when killed (deleted), calls a method of the other objects. Then these object erase any pointer to the deleted object. There are other classes, too. So this isn't really object oriented.
I actually think there is an easy solution that I can't find.
Essentially all these objects share ownership of this killable object. The strongest assurance you can give them is that it won't be deleted out from under them. You can accomplish that by giving each one a boost::shared_ptr. Notifying all the objects when it dies would allow them to drop their reference. You can use boost::signals to accomplish that. I would try for this first.
If you can't do that, then you could have them store a boost::weak_ptr and when their call to boost::weak_ptr::lock failed, they would know it was dead.