2011-05-11 74 views
1
template <class T> class purple_multitimer { 
public: 

typedef struct _timerinfo timerinfo, *ptimerinfo; 
typedef gboolean (T::*multitimer_callback) (ptimerinfo pti); 
typedef struct _timerinfo { 
    guint id; 
    multitimer_callback cb; 
    T * pthis; 
    purple_multitimer<T> * pmt; 
} timerinfo, *ptimerinfo; 

    purple_multitimer() { 
     memset(m_ti, 0, sizeof(m_ti)); 
    } 

    ~purple_multitimer() { 
     stop(); 
    } 

    void start(multitimer_callback mt_cb, T * pthis, guint timeout = 10) { 
     ptimerinfo pti = ti_get(); 
     assert(pti); 
     pti->pthis = pthis; 
     pti->pmt = this; 
     pti->cb = mt_cb; 
     pti->id = purple_timeout_add_seconds(timeout, GSourceFunc(timeout_cb), pti); 
    } 

    void stop(multitimer_callback mt_cb = NULL) { 
     for (register guint n = 0; n < sizeof(m_ti)/sizeof(timerinfo); ++ n) 
      if (m_ti[n].cb == mt_cb) { 
       purple_timeout_remove(m_ti[n].id); 
       ti_zero(n); 
      } 
    } 

private: 
    timerinfo m_ti[32]; 

    inline ptimerinfo ti_get(guint n) { 
     return &m_ti[n]; 
    } 

    inline ptimerinfo ti_get() { 
     for (register guint n = 0; n < sizeof(m_ti)/sizeof(timerinfo); ++ n) 
      if (m_ti[n].id == 0) return &m_ti[n]; 
     return NULL; 
    } 

    inline ptimerinfo ti_zero(ptimerinfo pti) { 
     memset(pti, 0, sizeof(timerinfo)); 
     return pti; 
    } 

    inline ptimerinfo ti_zero(guint n) { 
     memset(&m_ti[n], 0, sizeof(timerinfo)); 
     return &m_ti[n]; 
    } 

    static gboolean timeout_cb(ptimerinfo pti) { 
     gboolean res = (pti->pthis->*(pti->cb))(pti); 
     if (!res) pti->pmt->stop(pti->cb); 
     return res; 
    } 
}; 

class _ctrl { 
    public: 
    purple_multitimer<_ctrl> pmt; 

    gboolean on_tomeout (purple_multitimer<_ctrl>::ptimerinfo pti) { 
     return false; 
    }; 

    void on_connected(PurpleConnection *gc) { 
     pmt.start(purple_multitimer<_ctrl>::multitimer_callback(&_ctrl::on_tomeout), this); 
    } 

    void on_disconnected(PurpleConnection *gc) { 
    } 
} controller; 

当编译这段代码有错误:C++类的成员回调

[Error] E:\dnc-imexchange\dnc-imexchange.cpp:117: error: no matching function for call to `purple_multitimer<_ctrl>::start(gboolean (_ctrl::*)(_timerinfo*), _ctrl* const)' 
[Warning] E:\dnc-imexchange\dnc-imexchange.cpp:52: note: candidates are: void purple_multitimer<T>::start(gboolean (T::*)(_timerinfo*), T*, guint) [with T = _ctrl] 

我需要实现这样的方式回调!请帮助使它工作! 对不起,我的英语:)祝好,阿尔乔姆。

+0

此代码是草案。只需帮助解决回调问题。谢谢。 – Artem 2011-05-11 13:04:44

回答

3

如果你想要一些好品质的回调(能够同时调用多种功能,适合于观察者模式),可我建议boost::signals2

如果你只是想调用一个函数作为回调,您可以使用std ::功能:

void Foo(const std::function<bool (const int)> &callback) 
{ 
    const int number = 4; 
    if (callback(number)) 
    { 
     std::cout << "Callback returned true!" << std::endl; 
    } 
    else 
    { 
     std::cout << "Callback returned false!" << std::endl; 
    } 
} 

// Use this if you have C++11 

void CallFooLambda() 
{ 
    const auto lambda = [](const int number) -> bool 
    { 
     return number % 2; 
    }; 

    Foo(lambda); 
} 

// Else use these functions 

bool FooCallback(const int number) 
{ 
    return number % 2; 
} 

void CallFoo() 
{ 
    Foo(&FooCallback);  
} 
+0

我觉得这是矫枉过正,除非你实现Observer模式,即。多个用户需要回调单个事件。 – 2011-05-11 14:21:31

+0

为更简单的回调方法添加了编辑。 – 2012-05-08 12:40:26

0

的_CTRL是一个const指针,并尝试调用函数需要一个非const PTR -to_ctrl(pthis)。

0

你可以定义pthis如下?

T *pthis const 

这应该使您的代码与错误消息中的'候选'匹配。

this是,你不能改变的指针。

0

Boost.Function对于简化回调的语法和实现良好的工具包。

The Boost.Function library contains a family of class templates that are function object wrappers. The notion is similar to a generalized callback. It shares features with function pointers in that both define a call interface (e.g., a function taking two integer arguments and returning a floating-point value) through which some implementation can be called, and the implementation that is invoked may change throughout the course of the program.

Generally, any place in which a function pointer would be used to defer a call or make a callback, Boost.Function can be used instead to allow the user greater flexibility in the implementation of the target. Targets can be any 'compatible' function object (or function pointer), meaning that the arguments to the interface designated by Boost.Function can be converted to the arguments of the target function object.