【问题标题】:boost::shared_ptr parent <-> child communicationboost::shared_ptr 父 <-> 子通信
【发布时间】:2023-03-11 05:12:01
【问题描述】:

我正在使用 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 并在 boost::shared_ptr 中拥有这些到一个列表中。

现在孩子需要通知父母发生变化。这很容易,因为我将 CScene 的指针传递给 CSceneNode,节点知道它的父节点。由于节点不会比父节点活得更长,因此只需传递一个指针即可。

但父母也需要知道是谁回调它,这就是问题所在。父级不知道原始指针,它只知道共享指针,因此找出正在调用哪个子级的唯一方法是搜索所有节点以找到内部具有相同原始指针的节点,或者从原始指针创建另一个映射映射指向 shared_ptr 的指针。当一个节点被删除时,最后一个需要额外的维护。我也可以将 shared_ptr 传递给孩子本身,以帮助它把自己送回去,但这似乎很愚蠢。

谁能告诉我该怎么做?有没有更好的方法来做到这一点?

【问题讨论】:

    标签: c++ boost parent-child shared-ptr


    【解决方案1】:

    现在孩子需要通知父母发生变化。

    去掉这个要求,整个问题就崩溃了……还有你的循环依赖。

    您可以考虑使用基于事件的系统,或状态轮询。

    【讨论】:

    • 速度至关重要,因此不能选择轮询。基于事件会使这种方式过于复杂,因为需要通知父母的孩子很多。还是谢谢。
    • @scippie:轮询不需要影响“速度”。基于事件的系统通常比其他系统简单复杂。比 shared_ptr 依赖关系的纠结网络要好得多。我会重新考虑,因为我认为你的理由很站不住脚。
    • 我已经很好地考虑了这一点,我认为你是对的,我的 shader_ptr 确实被过度使用了。我已经简化了父子关系,但在需要的地方保留了 shared_ptr 的安全性。我也将你的答案标记为正确答案,虽然它不是我问题的答案,但只是因为其他有同样问题的人也应该阅读你的答案。
    【解决方案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;
    };
    

    【讨论】:

    • 我认为这是一个有用的提示,我不知道它存在!谢谢!
    • 虽然你的回答是我问题的准确答案,但我认为 Tomalak 给了我更好的答案。我听从了他的建议,没有使用你的解决方案。但这确实是我问题的答案,感谢您,我很感激能了解它。
    • @scippie - 没问题,感谢您的解释。很高兴在任何情况下都能提供帮助。
    【解决方案3】:

    如何在你的地图中覆盖谓词 less

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

    您可以通过指针进行比较,因此要找到指针,您只需从指针创建 shared_ptr 的临时实例。

    【讨论】:

    • 我不认为这很安全......这样你将有两个完全不同的shader_ptr指向同一个地址。如果第二个不再存在,则该对象将被删除,而另一个 shared_ptr 不需要。
    • @scippie - 同意,这就是为什么使用 insert 代替 [] 更安全 - 因为如果插入了新值或仅返回现有值,则 insert 返回 pair。
    猜你喜欢
    • 2013-06-28
    • 1970-01-01
    • 2012-12-19
    • 2017-12-26
    • 2018-12-22
    • 2011-03-04
    • 2011-06-16
    • 1970-01-01
    • 2017-03-14
    相关资源
    最近更新 更多