2014-12-04 62 views
3

我有一個管理多個「子」對象的生命週期的「父」對象。這些對象做了一些事情,並且在它們完成之後,它們通過回調信號通知其父(通過回調)它們已經完成並且可以被銷燬。如何在自己的回調中銷燬對象

,一種玩具,例如:

#include <list> 

class Child; 

class IChildListener 
{ 
public: 
    virtual void on_done(Child *child) = 0; 
}; 

class Child 
{ 
public: 
    Child(IChildListener *parent) 
     : m_parent(parent) 
    { 
    } 

    void do_stuff() 
    { 
     m_parent->on_done(this); 
    } 

protected: 

    IChildListener *m_parent; 
}; 

class Parent : public IChildListener 
{ 
public: 
    void on_done(Child* child) { 
     m_children.remove(child); 
     delete child; 
    } 

    Child *create_child() { 
     Child* child = new Child(this); 
     m_children.push_back(child); 
     return child; 
    } 
protected: 
    std::list<Child*> m_children;  
}; 

int main(int argc, char** argv) { 

    Parent p; 

    Child *c = p.create_child(); 

    c->do_stuff(); 
} 

的問題是,實際上是孩子自己的方法的調用期間被毀,這肯定不是一個好主意。有這樣的事情嗎?

+0

參見http://stackoverflow.com/questions/3150942/c-delete-this – 2014-12-04 21:54:12

回答

2

你的父類與垃圾收集器有很多相似之處,至少在玩具的例子中。 GC通常定期工作識別和處理垃圾;他們通常不會在他們變成垃圾時立即清理物體。

您的代碼可以做同樣的事情:父母的on_done()可以將指定的子對象移動到一次性子對象列表(垃圾),稍後它會在某些信號上進行清理。信號可以內置到create_child(),以便在創建新孩子之前清理所有完成的孩子。它也可以放入on_done(),以便以前的完成的孩子在信號被添加到完成的列表之前被清理。當然,你可以允許外部觸發清理。這些都不是彼此排斥的。

3

只要Childon_done()退出後不訪問自己的任何數據成員,那麼on_done()delete子對象是安全的。它與引用計數對象在引用計數降至0時釋放自己類似 - 當調用delete this時,對象的Release()方法仍在運行,但這是可以的,因爲Release()在調用delete後不訪問任何數據成員。

如果你真的想讓這個安全,你可以添加引用計數到你的Child類。當Parent將一個孩子添加到其列表中時,增加孩子的引用計數。當Parent從列表中刪除一個孩子時,減少孩子的引用計數。當Child調用on_done()時,它可以首先增加自己的引用計數,然後在on_done()退出後遞減引用計數。當引用計數達到0時,Child本身可以爲delete。這樣,Child決定何時可以安全地從內存中釋放自己,同時仍允許Parent管理子級列表。