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;
编译此代码时出错:
[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]
我需要以这种方式实现回调!请帮助它使它工作! 对不起我的英文:)最好的问候,Artem。
答案 0 :(得分:3)
如果你想要一些高质量的回调(能够同时调用多个函数,适合观察者模式),我可以建议boost::signals2。
如果您只想将一个函数作为回调调用,可以使用std :: function:
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);
}
答案 1 :(得分:0)
_ctrl是一个const指针,你试图调用的函数需要一个非const ptr-to _ctrl(pthis)。
答案 2 :(得分:0)
您能定义pthis
如下吗?
T *pthis const
这应该使您的代码与错误消息中的“候选人”匹配。
this
是一个无法改变的指针。
答案 3 :(得分:0)
Boost.Function是一个简化回调语法和实现的好工具包。
Boost.Function库包含一个 系列的类模板 函数对象包装器。这个概念 类似于广义回调。 它与功能共享功能 这两个指针都定义了一个调用 界面(例如,一个函数取两个 整数参数并返回一个 浮点值) 可以调用一些实现,和 调用的实现可能 在整个过程中改变 程序
一般来说,任何地方都有 函数指针将用于 推迟电话或回电, 可以使用Boost.Function代替 让用户更灵活 目标的实施。 目标可以是任何“兼容” 函数对象(或函数指针), 意思是说的 由Boost.Function指定的接口 可以转换为。的参数 目标函数对象。