2012-04-04 188 views
2

這是代碼,它非常簡單。C++ std :: bind保持對象存活

class Foo 
{ 
public: 
    void print() 
    { 
     std::cout<<"Foo::print\n"; 
    } 
}; 


Game::Game() 
{ 
    { 
     Foo foo; 
     player.onclick = bind(&Foo::print,foo); 

    } 
    player.onclick(); 
} 

內部範圍完成後的Foo對象超出範圍,但打印方法仍稱,我想這是因爲玩家擁有的Foo對象的引用?有沒有辦法阻止這種情況發生?我不希望物體活着,並在它們應該被銷燬時接收事件。

謝謝。

+1

該代碼不是直截了當的。其餘的在哪裏? – 2012-04-04 19:55:24

+0

你還需要什麼?綁定是std :: tr1 :: bind。 onclick是一個這樣的簡單功能 std :: function onclick; 也刪除了不必要的玩家的東西。 – 2012-04-04 19:58:16

+1

所以你使用tr1 :: bind。在這種情況下,我需要包括,主要等 – 2012-04-04 20:24:08

回答

4

您對foo的副本具有約束力;該複製持續的時間與綁定的函數對象一樣長,而原始foo在其作用域的末尾被銷燬。

如果您不想保留它,請將其綁定到指針(&foo)或引用(std::ref(foo));那麼一旦foo超出範圍,您必須小心不要調用函數對象。請注意,沒有辦法從函數對象中知道發生了這種情況;稱它會給未定義的行爲。

爲了在對象被銷燬時安全地斷開對象,您必須安排其析構函數重新指派onclick,或者讓其他對象負責首先重新指派onclick,然後銷燬該對象。

+0

好的,所以我改變了這個綁定: Foo foo; player.onclick =綁定(美孚::打印,&foo); 和印刷方法還是會被調用,不是我所期待的 – 2012-04-04 20:01:25

+3

@BlackKnight:是的,這個函數對象仍然是可調用的,但之後調用它破壞'foo'將會導致未定義的行爲(在這種情況下,這種行爲很可能會打印出消息,因爲成員函數對死對象沒有任何作用)如果你需要函數對象被安全地無效化,那麼你需要以某種方式自己去做 – 2012-04-04 20:03:24

+0

只有這樣,我才能看到處理是製作一個Foo析構函數並設置一個殭屍標誌,然後在處理程序立即返回時如果對象已死亡。 player.onclick和Foo.print之間的綁定? – 2012-04-04 20:07:14

0

從您的描述中,它聽起來像是你真的想要一個事件循環。雖然std::bind對於這樣的事情是有用的,但它本身並不是全部。我建議你看看boost.signals

0

我認爲你應該使用shared_ptr當你將FooPlayer,並保持weak_ptrFooPlayer。然後嘗試在onclick函數中鎖定weak_ptr以查看Foo是否仍然存在。類似這樣的:

using namespace std; 
class Foo 
{ 
    public: 
     void print() 
     { 
      cout<<"Foo::print\n"; 
     } 
}; 

class Player 
{ 
    public: 
     weak_ptr<function<void()>> _onClickFuntion; 
     void onclick() 
     { 
      shared_ptr<function<void()>> tempFunction(_onClickFunction.lock()); 
      if (tempFunction) 
       tempFunction(); 
     } 
} 

Game::Game() 
{ 
    { 
     Foo foo; 
     player._onClickFuntion = shared_ptr<function<void()>>(new bind(&Foo::print,foo)); 
    } 
    player.onclick(); 
}