使用类成员的 C++ 回调

2021-12-07 00:00:00 function callback c++ member

我知道这个问题已经被问过很多次了,正因为如此,我很难深入挖掘这些问题并找到一个简单的例子来说明什么是有效的.

I know this has been asked so many times, and because of that it's difficult to dig through the cruft and find a simple example of what works.

我知道了,它很简单,适用于 MyClass...

I've got this, it's simple and it works for MyClass...

#include <iostream>
using std::cout;
using std::endl;

class MyClass
{
    public:
        MyClass();
        static void Callback(MyClass* instance, int x);
    private:
        int private_x;
};

class EventHandler
{
    public:
        void addHandler(MyClass* owner)
        {
            cout << "Handler added..." << endl;
            //Let's pretend an event just occured
            owner->Callback(owner,1);
        }
};

EventHandler* handler;

MyClass::MyClass()
{
    private_x = 5;
    handler->addHandler(this);
}

void MyClass::Callback(MyClass* instance, int x)
{
    cout << x + instance->private_x << endl;
}

int main(int argc, char** argv)
{
    handler = new EventHandler();
    MyClass* myClass = new MyClass();
}

class YourClass
{
    public:
        YourClass();
        static void Callback(YourClass* instance, int x);
};

如何重写,以便 EventHandler::addHandler() 可以与 MyClassYourClass 一起使用.我很抱歉,但这只是我大脑的工作方式,我需要先看看一个简单的例子,然后才能理解它为什么/如何工作.如果您有最喜欢的方法来完成这项工作,现在是时候展示它了,请标记该代码并将其发回.

How can that be rewritten so EventHandler::addHandler() will work with both MyClass and YourClass. I'm sorry but it's just the way my brain works, I need to see a simple example of what works before I can comprehend why/how it works. If you've got a favorite way to make this work now's the time to show it off, please markup that code and post it back.

有人回答了,但在我打勾之前答案就被删除了.就我而言,答案是模板化函数.将 addHandler 更改为此...

It was answered but the answer was deleted before I could give the checkmark. The answer in my case was a templated function. Changed addHandler to this...

class EventHandler
{
    public:
        template<typename T>
        void addHandler(T* owner)
        {
            cout << "Handler added..." << endl;
            //Let's pretend an event just occured
            owner->Callback(owner,1);
        }
};

推荐答案

您可以使用新的 C++11 标准中的功能,而不是使用静态方法和传递指向类实例的指针:std::functionstd::bind:

Instead of having static methods and passing around a pointer to the class instance, you could use functionality in the new C++11 standard: std::function and std::bind:

#include <functional>
class EventHandler
{
    public:
        void addHandler(std::function<void(int)> callback)
        {
            cout << "Handler added..." << endl;
            // Let's pretend an event just occured
            callback(1);
        }
};

addHandler 方法现在接受一个 std::function 参数,并且这个函数对象"没有返回值并且接受一个整数作为参数.

The addHandler method now accepts a std::function argument, and this "function object" have no return value and takes an integer as argument.

要将其绑定到特定函数,请使用 std::bind:

To bind it to a specific function, you use std::bind:

class MyClass
{
    public:
        MyClass();

        // Note: No longer marked `static`, and only takes the actual argument
        void Callback(int x);
    private:
        int private_x;
};

MyClass::MyClass()
{
    using namespace std::placeholders; // for `_1`

    private_x = 5;
    handler->addHandler(std::bind(&MyClass::Callback, this, _1));
}

void MyClass::Callback(int x)
{
    // No longer needs an explicit `instance` argument,
    // as `this` is set up properly
    cout << x + private_x << endl;
}

您需要在添加处理程序时使用 std::bind,因为您需要明确指定其他隐式的 this 指针作为参数.如果你有一个独立的函数,你就不必使用 std::bind:

You need to use std::bind when adding the handler, as you explicitly needs to specify the otherwise implicit this pointer as an argument. If you have a free-standing function, you don't have to use std::bind:

void freeStandingCallback(int x)
{
    // ...
}

int main()
{
    // ...
    handler->addHandler(freeStandingCallback);
}

让事件处理程序使用 std::function 对象,还可以使用新的 C++11 lambda 函数:

Having the event handler use std::function objects, also makes it possible to use the new C++11 lambda functions:

handler->addHandler([](int x) { std::cout << "x is " << x << '
'; });

相关文章