C ++类成员回调

时间:2011-05-11 13:02:37

标签: c++ class templates callback member

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。

4 个答案:

答案 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指定的接口   可以转换为。的参数   目标函数对象。