2011-09-08 50 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

相關問題