2014-12-04 2 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 –

답변

2

부모 클래스는 적어도 장난감 예에서는 가비지 수집기와 상당히 유사합니다. GC는 일반적으로 으로 일하고 있습니다. 쓰레기는 식별하고 처리합니다. 그들은 대개 쓰레기가되는 즉시 물건을 청소하지 않습니다.

코드는 동일하게 처리 할 수 ​​있습니다. 부모의 on_done()이 지정된 자식 개체를 일회용 자식 목록 (가비지)으로 이동할 수 있습니다.이 자식 개체는 나중에 일부 신호에서 정리됩니다. 신호는 create_child()으로 빌드 될 수 있으므로 새 하위가 작성되기 전에 완성 된 하위가 정리됩니다. 또한 on_done()에 넣을 수 있으므로 이전에 명의 완성 된 어린이는 신호가 완성 된 어린이보다 먼저 정리됩니다. 물론 외부에서 정리 작업을 수행 할 수도 있습니다. 이들 중 어느 것도 서로 독점적이지 않습니다.

3

on_done() 종료 후 Child이 자신의 데이터 멤버에 액세스하지 않는 한 on_done() ~ delete 자식 개체는 안전합니다. 참조 카운트 된 객체가 참조 카운트가 0이 될 때 해제되는 것과 비슷하지만 메서드가 여전히 실행 중일 때 이 호출되었지만 이 delete을 호출 한 후 데이터 멤버에 액세스하지 않기 때문에 정상입니다.

이 안전 장치를 실제로 만들고 싶다면 Child 클래스에 참조 계산을 추가 할 수 있습니다. Parent이 해당 목록에 자식을 추가하면 해당 자식의 참조 횟수를 증가시킵니다. Parent이 목록에서 자식을 제거하면 자식 참조 수를 감소시킵니다. Childon_done()을 호출하면 먼저 자신의 참조 횟수를 증가시킨 다음 on_done() 종료 후 참조 횟수를 감소시킵니다. 참조 횟수가 0이되면 Childdelete 일 수 있습니다. 이렇게하면 Child은 메모리에서 스스로를 해제하는 것이 안전 할 때를 결정하고 Parent은 자식 목록을 관리 할 수 ​​있습니다.

관련 문제