boost::shared_ptr parent <-> child communication
I am using boost::shared_ptr to organize my pointer data in my game engine.
I tried to make a very short example to show my problem:
class CSceneNode
{
public:
CSceneNode(CScene *p) : parent(p) {}
void foo() {
parent->notifyThatFooWasCalledOnMe(my_shared_ptr_version_of_this???);
};
CScene *parent;
};
class CScene
{
public:
void addNode() {
nodes.push_back(boost::shared_ptr<CSceneNode>(new CSceneNode(this)));
}
void notifyThatFooWasCalledOnMe(boost::shared_ptr<CSceneNode> node) {
foo_was_called[node] = true;
}
std::list<boost::shared_ptr<CSceneNode> > nodes;
std::map<boost::shared_ptr<CSceneNode>, bool> foo_was_called;
};
Thus the problem is: CScene creates CSceneNode's and owns these in boost::shared_ptr's into a list.
Now the child needs to notify the parent of a change. This is easy, as I passed the point开发者_如何学Goer of CScene onto CSceneNode, the node knows its parent. As the node will not live longer than the parent, it is ok to just pass a pointer.
But the parent also needs to know who it is that calls it back, and there's the problem. The parent doesn't know the raw pointers, it only knows shared pointers, so the only way to find out which child is calling is searching over all nodes to find that one with the same raw pointer inside, or create another map mapping from raw pointer to shared_ptr. This last one then needs extra maintenance when a node is deleted. I could also pass the shared_ptr to the child itself to help it send itself back, but that seems stupid.
Can anyone tell me what to do? Is there a better way to do this?
Now the child needs to notify the parent of a change.
Remove this requirement, and the whole problem collapses... as well as your cyclic dependency.
You might consider an event-based system instead, or state polling.
It looks like you might want to use enable_shared_from_this<>, which is a way for an object to be aware of its own shared_ptr<> ownership.
So...
class CSceneNode : public boost::enable_shared_from_this<CSceneNode> // <- (1)
{
public:
CSceneNode(CScene *p) : parent(p) {}
void foo() {
parent->notifyThatFooWasCalledOnMe(shared_from_this()); // <- (2)
};
CScene *parent;
};
What about to override predicate less in your map
std::map<boost::shared_ptr<CSceneNode>, bool, MyLess>
You could compare by pointer, so to locate pointer you just need create temp instance of shared_ptr from pointer.
精彩评论