【问题标题】:C++ Class member callbackC++ 类成员回调
【发布时间】:2011-08-23 07:25:57
【问题描述】:

我在编译这段代码时出错:

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]

我需要以这种方式实现回调。

【问题讨论】:

  • 此代码为草稿。只是帮助解决回调问题。谢谢。

标签: c++ class templates callback member


【解决方案1】:

如果你想要一些高质量的回调(可以同时调用多个函数,适合观察者模式),我建议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);    
}

【讨论】:

  • 我认为这是矫枉过正,除非你正在实现观察者模式,即。多个订阅者需要回调单个事件。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    你能定义pthis如下吗?

    T *pthis const
    

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

    this 是一个不能更改的指针。

    【讨论】:

      【解决方案4】:

      Boost.Function 是一个很好的简化回调语法和实现的工具包。

      Boost.Function 库包含一个 类模板系列 函数对象包装器。观念 类似于广义回调。 它与功能共享功能 两者都定义调用的指针 接口(例如,一个函数需要两个 整数参数并返回一个 浮点值)通过它 可以调用一些实现,并且 被调用的实现可能 在整个过程中发生变化 程序。

      一般来说,任何地方 函数指针将用于 推迟通话或回拨, Boost.Function 可以用来代替 允许用户更大的灵活性 目标的实施。 目标可以是任何“兼容的” 函数对象(或函数指针), 这意味着对 Boost.Function 指定的接口 可以转换为参数 目标函数对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-20
        • 1970-01-01
        • 2012-03-04
        • 1970-01-01
        • 2010-11-03
        • 1970-01-01
        相关资源
        最近更新 更多