简体   繁体   中英

C++ Class member callback

I have an error compiling this code:

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;

When compiling this code got error:

[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]

I need to implement callbacks in such way.

If you want some good quality callbacks (able to call multiple functions at once, suitable for observer pattern), may I suggest boost::signals2 .

If you just want to call one function as a callback you can use 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);    
}

_ctrl是const指针,并且您尝试调用的函数需要非const ptr-to _ctrl(pthis)。

Can you define pthis as follows?

T *pthis const

That should make your code match the 'candidate' in the error message.

this is a pointer that you can't change.

Boost.Function is a good toolkit for simplifying callback syntax and implementation.

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 (eg, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM