2011-08-23 63 views
2

我有以下的情況,(在代碼更好)C++成員函數的指針,升壓::信號

class Foo 
    { 
private: 
     typedef boost::signal<void()> Signal; 
     Signal signal; 

public: 
     void Register_SignalFunction(const Signal::slot_type& slot); 
     void Unregister_SignalFunction(const Signal::slog_type& slot); 
    } 

    class OtherFoo 
    { 
     Foo foo; 
public: 
     OtherFoo() 
     { 
      foo.Register_SignalFunction(&OnSignal) //I know I can't do this that is precisely my question. 
     } 

     void OnSignal(); //what to do when signal fires 
    } 

所以,問題是,如何通過一個「成員函數」指針寄存器的方法。另外,這是好嗎?我想/需要的是某種委託註冊系統,所以如果任何人都無法指出我的方向,我會很感激。提前Thanx。

回答

1

通常你要麼做:

void Register_SignalFunction(const boost::function<void()> &slot) { 
    signal += slot; 
} 

,或者作爲內嵌功能:

template<typename T> 
void Register_SignalFunction(T &slot) { 
    signal += slot; 
} 

後者可能是通過去除間接boost::function層會更有效了 - 但只假設boost::signal內部不使用boost::function(它很可能)。所以,使用你喜歡的任何一個,真的。

3

您通常使用升壓綁定:

foo.Register_SignalFunction(升壓::綁定(& OtherFoo :: OnSignal,這個));

這是怎麼回事? :-)

信號的連接方法需要一個仿函數。這是一個實現()運算符的對象。綁定需要函數指針(或者釋放函數或者成員函數)並且返回一個具有正確簽名的函子。

而且在這裏看到:

Complete example using Boost::Signals for C++ Eventing

這裏:

how boost::function and boost::bind work

要斷開信號存儲返回值從連接成:

boost::signals::connection 

而且然後撥打斷開ct方法。

+0

每當我嘗試做一些類似foo我得到這個錯誤。Register_SignalFunction(boost :: bind(&OtherFoo :: OnSignal,this));錯誤C2678:二進制'==':找不到操作符找到類型爲'const boost :: slot '的左手操作數是不可接受的轉換)\t f:\ development \ boost_1_41_0 \ boost \ function_equal.hpp Indigen_Framework – Yoss

+0

@Yoss:我認爲你的Signal typedef必須是公開的。除此之外,請發佈一個最小的可編譯示例。您當前的代碼中存在拼寫錯誤,例如Signal :: slog_type ... –

0

我得到了它想要了很多工作後,下面的代碼:

GraphicsDeviceManager 
{ 
    private: 
     typedef boost::signal<void()> DeviceLost; 
     DeviceLost deviceLost; 

    public: 
     Register_DeviceLostHandler(const boost::function<void()> &handler) 
     { 
      deviceLost.connect(slot); 
     } 
     Unregister_DeviceLostHandler(const boost::function<void()> &handler) 
     { 
      //deviceLost.disconnect(slot); 
     } 
} 

class GameBase 
{ 
    private: 
    GraphicsDeviceManager* graphics; 

    public: 
     GameBase() 
     { 
      graphics = new GraphicsDeviceManager(); 
      graphics->Register_DeviceLostHandler(boost::bind(&GameBase::OnDeviceLost, this)); 
     } 
     void OnDeviceLost() 
     { 
      //do some stuff 
     } 
} 

以及此代碼的工作,因爲它應該是一個例外,如果我unccomment的deviceLost.disconnect(處理器)語句,我收到編譯錯誤,如: 錯誤C266「boost :: operator ==」:4重載有類似的轉換。

那麼,爲什麼會發生這種情況呢?你知道任何其他方式來完成我想要的嗎?

+0

Ps:對不起,如果您看到錯別字,我輸入了代碼,我沒有從Visual Studio複製/粘貼。 – Yoss

+0

你不會那樣斷開連接。你的註冊函數應該返回一個boost :: signals :: connection,然後你使用它來斷開連接。查看我的答案和Boost信號文檔。 –

0

如果有人想要一個完整的例子:

#include <iostream> 
#include <boost/signals2/signal.hpp> 
#include <boost/bind.hpp> 
#include <boost/optional/optional_io.hpp> 

#define registerEvent_(A) registerEvent(boost::bind(A, this, _1, _2)) 

struct A 
{ 
    typedef boost::signals2::signal<int (int &, int &)> EventSignal; 
    typedef EventSignal::slot_type SlotType; 

    void registerEvent(const SlotType & slot); 
    void triggerAll(int& a1, int& a2); 

    EventSignal signal_; 
}; 

void A::registerEvent(const SlotType & slot) { signal_.connect(slot); } 
void A::triggerAll(int& a1, int& a2) {std::cout << signal_(a1, a2) << "\n";} 

struct B : public A 
{ 
    B(); 
    int myFunc(int& a1, int& a2); 
}; 

B::B() { 
#ifdef WITHMACRO 
    registerEvent_(&B::myFunc); 
#else 
    registerEvent(boost::bind(&B::myFunc, this, _1, _2)); 
#endif 
} 
int B::myFunc(int& a1, int& a2) { return a1 + a2 + 1; } 

int main() 
{ 
    int a1 = 2; 
    int a2 = 3; 
    B b; 
    b.triggerAll(a1, a2); 
}