简体   繁体   English

在没有C ++ 11的情况下用C ++做最简单的回调方法?

[英]Cleanest way to do callbacks in C++ without C++11?

What is the cleanest way to do callbacks to a class in C++? 在C ++中对类进行回调的最简洁方法是什么?

I usually create a function like: 我通常会创建一个函数:

void registerCallback(void(*callback)(void* param), void* param);

And then call it like such: 然后像这样称呼它:

foo->registerCallback(callbackStatic, this);

Then I add a static function in my class like such: 然后我在我的类中添加一个静态函数,如:

static void callbackStatic(void* param)
{
    ((Type*)(param))->callback();
}

It works, but it's a pain. 它有效,但这很痛苦。 I have to create two functions per callback. 我必须为每个回调创建两个函数。 If I could use C++11, I'd use a lambda instead. 如果我可以使用C ++ 11,我会使用lambda代替。 Qt has a very nice signal and slot mechanism, but requires a special pre-compiler. Qt有一个非常好的信号和插槽机制,但需要一个特殊的预编译器。

I'm writing a library, so I'd like to keep the requirements as low as possible. 我正在写一个库,所以我想保持尽可能低的要求。 No C++11, no boost, etc. Is there a way to build a lambda or signal/slot 'like' callback system only using C++03? 没有C ++ 11,没有提升等。有没有办法只使用C ++ 03构建一个lambda或信号/槽'之类''回调系统?

If you are able to start from scratch, I recommend not using functions for callbacks in C++. 如果你能够从头开始,我建议不要在C ++中使用函数进行回调。 Instead, use objects. 相反,使用对象。

struct CallbackHandler { virtual void doit() = 0; };

void registerCallback(Callbackhandler* handler);

and then 然后

struct MyCallbackHandler : public CallbackHandler { ... };

registerCallback(new MyCallbackHandler());

Is there a way to build a lambda or signal/slot 'like' callback system only using C++03? 有没有办法只使用C ++ 03构建lambda或signal / slot'之类''回调系统?

Another way is to use just plain old pure abstract interfaces. 另一种方法是使用普通的纯抽象接口。 This wouldn't require that 2 stage reinforcement of class member functions through the callback function, but just use virtual polymorphism. 这不需要通过回调函数对类成员函数进行2阶段强化,而只需使用虚拟多态。

You could even use static polymorphism aka as CRTP which also works with the pre c++11 standard. 您甚至可以使用静态多态,也称为CRTP,它也适用于pre c ++ 11标准。

That all worked from the early standardisations onwards. 这一切都从早期的标准化开始起作用。


Code samples at @R Sahu's answer 代码示例@R Sahu的回答

This might be a bit complicated, but it works for me: 这可能有点复杂,但它对我有用:

#include <functional>
#include <iostream>
#include <vector>

class C {
public:
    void foo() {
        std::cout << "foo" << std::endl;
    }
};

class D {
public:
    void bar() {
        std::cout << "bar" << std::endl;
    }
};

class abstract_bind {
public:
    virtual void operator()() = 0;
    virtual ~abstract_bind() {}
};

template <typename F, typename T>
class bind : public abstract_bind {
public:
    bind(F f_, T *t_) : f(f_), t(t_) {}

    virtual void operator()() {
        f(t);
    }

private:
    F f;
    T *t;
};


int main() {
    C c1, c2;
    D d;

    std::vector<abstract_bind*> v;

    v.push_back(new bind<std::mem_fun_t<void, C>, C>(std::mem_fun(&C::foo), &c1));
    v.push_back(new bind<std::mem_fun_t<void, C>, C>(std::mem_fun(&C::foo), &c2));
    v.push_back(new bind<std::mem_fun_t<void, D>, D>(std::mem_fun(&D::bar), &d));

    for (size_t i=0; i<v.size(); ++i)
        (*v[i])();

    for (size_t i=0; i<v.size(); ++i)
        delete v[i];

    return 0;
}

The basic idea is that you use std::mem_fun to get the object's member function and bind the corresponding this pointer to it to get "plain" function. 基本思想是使用std::mem_fun获取对象的成员函数,并将相应的this指针绑定到它以获得“plain”函数。

You might keep the C-style callbacks and use a structure for invoking member functions: 您可以保留C样式的回调并使用结构来调用成员函数:

// C-style callback
// ================

void(*registered_callback)(void* param) = 0;
void* registered_param = 0;
void registerCallback(void(*callback)(void* param), void* param) {
    registered_callback = callback;
    registered_param = param;
}
void unregisterCallback(void(*callback)(void* param), void* param) {
    registered_callback = 0;
    registered_param = 0;
}

// Invoker
// =======

struct InvokerBase {
    static void callInvoker(void* invoker) {
        reinterpret_cast<InvokerBase*>(invoker)->apply();
    }

    virtual void apply() const = 0;
};

template <typename T>
class Invoker : public InvokerBase
{
    public:
    Invoker(T& object, void(T::*function)())
    : object(&object), function(function)
    {
        registerCallback(callInvoker, this);
    }
    ~Invoker() {
        unregisterCallback(callInvoker, this);
    }

    void apply() const {
        (object->*function)();
    }

    private:
    Invoker(const Invoker&); // no copy
    Invoker& operator = (const Invoker&); // no copy

    T* object;
    void (T::*function)();
};


// Test
// ====

#include<cassert>
#include<iostream>

struct Type {
    void print() { std::cout << "Hello\n"; }
};

int main()
{
    Type x;
    {
        Invoker<Type> print_invoker(x, &Type::print);
        registered_callback(registered_param);
    }
    assert(registered_callback == 0);
}

You could try Synapse, it is a signal-slot library that requires no precompiling. 你可以试试Synapse,它是一个信号槽库,不需要预编译。 In Synapse any object whatsoever can be used as an emitter: http://zajo.github.io/boost-synapse/ 在Synapse中,任何对象都可以用作发射器:http: //zajo.github.io/boost-synapse/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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