boost :: shared_ptr parent <-> дочернее общение - PullRequest
0 голосов
/ 08 сентября 2011

Я использую 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, узел знает своего родителя. Поскольку узел не будет жить дольше, чем родительский, можно просто передать указатель.

Но родителю также нужно знать, кто это вызывает, и есть проблема. Родитель не знает необработанных указателей, он знает только общие указатели, поэтому единственный способ выяснить, какой дочерний объект вызывает, - это поиск по всем узлам, чтобы найти тот с тем же указателем raw внутри, или создание другого сопоставления карты из raw указатель на shared_ptr. Этот последний требует дополнительного обслуживания, когда узел удаляется. Я также мог бы передать shared_ptr самому ребенку, чтобы он мог отправить себя обратно, но это кажется глупым.

Может кто-нибудь сказать мне, что делать? Есть ли лучший способ сделать это?

Ответы [ 3 ]

3 голосов
/ 08 сентября 2011

Теперь ребенок должен уведомить родителя об изменении.

Уберите это требование, и вся проблема рухнет ... как и ваша циклическая зависимость.

Вместо этого вы можете рассмотреть систему, основанную на событиях, или опрос состояния.

2 голосов
/ 08 сентября 2011

Похоже, вы, возможно, захотите использовать 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 голосов
/ 08 сентября 2011

Как насчет переопределения предиката меньше на вашей карте

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

Вы можете сравнить по указателю, поэтому чтобы найти указатель, вам просто нужно создать временный экземпляр shared_ptr из указателя.

...