使用类成员的 C 回调

新手上路,请多包涵

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

我有这个,它很简单,适用于 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 。很抱歉,但这只是我大脑的工作方式,我需要先看一个简单的例子来说明什么是有效的,然后才能理解它为什么/如何工作。如果您有最喜欢的方式来完成这项工作,现在是展示它的时候了,请标记该代码并将其发回。

[编辑]

它已被回答,但在我打勾之前答案已被删除。就我而言,答案是模板化函数。将 addHandler 更改为此…

 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);
        }
};

原文由 BentFX 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 335
2 个回答

您可以使用新的 C++11 标准中的功能,而不是使用静态方法并传递指向类实例的指针: std::functionstd::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 参数,并且这个“函数对象”没有返回值并且接受一个整数作为参数。

要将其绑定到特定函数,请使用 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

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

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

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

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

原文由 Some programmer dude 发布,翻译遵循 CC BY-SA 3.0 许可协议

来自上述代码的完整工作示例……对于 C++11:

 #include <stdlib.h>
#include <stdio.h>
#include <functional>

#if __cplusplus <= 199711L
  #error This file needs at least a C++11 compliant compiler, try using:
  #error    $ g++ -std=c++11 ..
#endif

using namespace std;

class EventHandler {
    public:
        void addHandler(std::function<void(int)> callback) {
            printf("\nHandler added...");
            // Let's pretend an event just occured
            callback(1);
        }
};

class MyClass
{
    public:
        MyClass(int);
        // Note: No longer marked `static`, and only takes the actual argument
        void Callback(int x);

    private:
        EventHandler *pHandler;
        int private_x;
};

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

    pHandler = new EventHandler();
    private_x = value;
    pHandler->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
    printf("\nResult:%d\n\n", (x+private_x));
}

// Main method
int main(int argc, char const *argv[]) {

    printf("\nCompiler:%ld\n", __cplusplus);
    new MyClass(5);
    return 0;
}

// where $1 is your .cpp file name... this is the command used:
// g++ -std=c++11 -Wall -o $1 $1.cpp
// chmod 700 $1
// ./$1

输出应该是:

 Compiler:201103

Handler added...
Result:6

原文由 Craig D 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题