2011-09-08 30 views
0

我使用boost :: shared_ptr来组织我的游戏引擎中的指针数据。boost :: shared_ptr父<->子通信

我试图做一个很短的例子来说明我的问题:

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; 
}; 

因此,问题是: CScene创建CSceneNode的,拥有这些在升压:: shared_ptr的的到一个列表。

现在孩子需要通知父母变更。这很容易,因为我将CScene的指针传递到CSceneNode,节点知道它的父节点。由于节点的寿命不会超过父节点,因此只需传递一个指针即可。

但父母也需要知道是谁回电,并且存在问题。父母不知道原始指针,它只知道共享指针,因此唯一能找出哪个孩子正在调用的方法是在所有节点上搜索,找到其中一个具有相同原始指针的人,或者从原始地址创建另一个地图映射指向shared_ptr的指针。当最后一个节点被删除时,需要额外的维护。我也可以将shared_ptr传递给孩子,以帮助孩子回到自己身边,但这看起来很愚蠢。

有谁能告诉我该怎么办?有一个更好的方法吗?

回答

3

现在孩子需要通知的改变的父。

删除此要求,整个问题崩溃......以及您的循环依赖。

您可能会考虑基于事件的系统或状态轮询。

+0

速度是至关重要的,因此投票不是一种选择。基于事件会使这种方式太复杂,因为它是很多需要通知父母的孩子。不管怎么说,还是要谢谢你。 – scippie

+0

@scippie:轮询不需要影响“速度”。基于事件的系统通常比替代品复杂。比缠绕着'shared_ptr'依赖关系的网络好得多。我会重新考虑一下,因为我认为你的理由很脆弱。 –

+0

我已经认为这非常好,我认为你是对的,我的shader_ptr的确被过度使用。我已经简化了父母与子女之间的关系,但是已经将shared_ptr的安全保留在需要的地方。我也将你的答案标记为正确的答案,尽管这不是我的问题的答案,但仅仅是因为其他具有相同问题的人也应该阅读你的答案。 – scippie

2

看起来您可能想要使用enable_shared_from_this<>,这是对象了解其自己的shared_ptr所有权的一种方式。

所以......

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; 
}; 
+0

我认为这是一个有用的提示,我不知道这存在!谢谢! – scippie

+0

虽然你的回答是我的问题的确切答案,但我认为Tomalak给了我一个更好的答案。我遵循他的建议,并没有使用你的溶剂。但是的确,这是我的问题的答案,我很感谢您了解了这一点。 – scippie

+0

@scippie - 没问题,谢谢你的解释。很高兴在任何情况下都有所帮助。 –

0

关于地图

std::map<boost::shared_ptr<CSceneNode>, bool, MyLess> 

您可以通过指针比较重写谓语少,所以定位指针,你只需要从指针创建的shared_ptr临时实例什么。

+0

我不认为这是相当安全的工作...有了这个,你将有两个完全不同的shader_ptr指向相同的地址。如果第二个停止存在,则该对象将被删除,而其他shared_ptr不需要该对象。 – scippie

+0

@scippie - 同意,这就是为什么而不是[insert]的使用更安全 - 因为插入返回对,如果插入了新值或只返回现有值。 – Dewfy

相关问题