• Advertisement
Sign in to follow this  

Is this a valid situation to use enable_shared_from_this?

This topic is 2776 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In my single player RPG (C++/Boost/Allegro), whenever a character dies, everyone who was targeting this character must be notified so that the AI can change its behaviour.

I'm thinking of giving each character a list of other characters who are targeting it (a list "targeters"), and then broadcasting a message to each of them when the character dies.

All my pointers are boost::shared_ptrs, and all characters are created on the heap.


class Character
{
//...

// List of characters who target this character
std::vector< boost::shared_ptr<Character> > targeters;

// Iterates over targeters and tells everyone this character died
void broadcastDeath();

//...
}

// Called when this starts fighting target
void Character::startFighting( boost::shared_ptr<Character> target )
{
this->fightingTarget = target;
target->addTargeter( this ); // here's the problem
this->pushAiState(ais_fight);
}


Since I cannot directly get a shared pointer from this, would this be a valid situation to use boost::enable_shared_from_this?

I could also make the targeters vector save raw pointers, but I don't like this idea. There may be other situations where I need take a member from the targeters vector and pass it to a function which takes a shared_ptr as an argument. Also, I'm not sure if it's safe to have a vector which saves a raw pointer to X and at the same time have other vectors which save shared_ptr to X (all the other "list of characters" vectors in my game save shared_ptrs).

What would you do in this situation?

Share this post


Link to post
Share on other sites
Advertisement
I think it's a perfectly valid situation. I prefer to use a shared_ptr over a raw one 99% of the time.

However maybe you could circumvent this situation: Where do you detect if a fight is started? Also, where do you detect if a player is dead? If you've introduced another class/method that has access to the shared_ptr of both players involved, then he can distribute the message himself.

It is safe to store a vector with raw pointers to x, but if you can ensure to not use them when the shared/auto_ptr has gone out of scope. A better way to keep a sequence of pointers without implying ownership semantics is to have a sequence of weak_ptrs, imo.

Share this post


Link to post
Share on other sites
Sure, this is a common use of shared_from_this. Of course, you should consider the ramifications of storing a shared_ptr like that, which will keep the object from being freed as long as someone has it in their targeters; better would be to keep a weak_ptr.

By the way, if you're doing events, and you're already using boost, take a look at boost.signals2, a signal/slot system which is already integrated with shared_ptr/weak_ptr for that sort of connection management.

Share this post


Link to post
Share on other sites
Thanks to both of you.

Quote:
Original post by Sneftel
By the way, if you're doing events, and you're already using boost, take a look at boost.signals2, a signal/slot system which is already integrated with shared_ptr/weak_ptr for that sort of connection management.


This would have been my second question: would you recommend using the boost signal library instead of my own notification system? I'm concerned it could a little overkill. Which approach would you take yourself?

Share this post


Link to post
Share on other sites
Not sure what you mean by "overkill".

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Not sure what you mean by "overkill".


overkill = not much additional benefit compared to simpler system

Share this post


Link to post
Share on other sites
That implies, though that the costs are not the same. What costs are you worried about? The difficulty of learning boost.signal? The complexity of the code necessary to use it? The runtime cost of using it? (Who knows, no, probably not.)

Share this post


Link to post
Share on other sites
Another option is to use intrusive_ptr rather than shared_ptr if you find yourself using shared_from_this a whole lot. Of course, that's not an option if you need weak_ptr or want to use the integration with the signals library.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement