我可以使用std :: bind将指针转换为成员函数的指针转换为函数的指针

Can I use std::bind to convert a pointer to member function into a pointer to function?

本文关键字:指针 函数 转换 成员 可以使 std bind 我可以      更新时间:2023-10-16

我想通过呼叫函数传递成员函数。回电是基本功能指针。

所以我有类似的东西:

h文件:

void (*pRequestFunc) (int someint) = 0;
void RegisterRequestCallBack(void (*requestFunc) (int someint))
{
    pRequestFunc = requestFunc;
}
class A
{
    void callBack(int someint);
}

CPP文件:

RegisterRequestCallBack(&A::callBack); // This does not work.

注意我试图从我的较大示例中提取此示例并删除所有其他内容 - 因此它可能不是完美的。

据我了解,

问题是,成员函数指针确实(在引擎盖下(具有额外的参数(和实例 - 即this(,并且与正常函数指针不兼容。

RegisterRequestCallBack()实际上不是我的代码 - 所以我无法更改。

所以我阅读了boost :: bind可以做我需要的事情 - 我希望C 11 std :: bind可以做同样的事情 - 但我无法弄清楚如何使用它来有效地获得标准功能来自成员功能指针的指针...

我正在寻找:

std::bind(&A::callBack) ...就我而言,我对在线示例的理解很差:(

nathanoliver的评论是正确的,您的怀疑大多是正确的。确切地没有指定指向成员函数的指示,而包括this作为隐藏参数主要是的工作。您只需要一些额外的工作来继承和指示virtual功能(是的,您也可以接受它们的地址(。

现在,回调通常包括您控件下的void*参数,您可以使用该参数传递A*。在这种情况下,您可以编写一个包装器(static(功能,该功能将void*投入到A*并对&A::callback进行实际调用。

这里并非如此。注册采用一个无数据的功能。为了使其在现实生活中工作,您必须求助于急剧解决方案 - 而不是便携式C 。一种这样的方法是动态生成汇编(!(。您在运行时创建 - 相当于

的编译
void __trampoline_0x018810000 (int i)
{
   A* __this = reinterpret_cast<A*>(0x018810000);
   __this->callback(i);
}

如您所见,您必须为每个A*值生成一个蹦床,而管理这些值是重大痛苦。

能够绑定到需要执行的成员函数:

std::function<void(int)> function = std::bind(&A::foo, this, std::placeholders::_1);

或您的情况:

RegisterRequestCallBack(std::bind(&A::callback, this, std::placeholders::_1));

,但我认为实现这一目标的最清晰方法是使用lambda功能。在这里,您有一个可以激发您灵感的类似事情的示例:

#include <array>
#include <map>
#include <vector>
#include <functional>
#include <iostream>
class TaskManager {
    public:
        using task_t = std::function<void()>;
        void run();
        void addTask(task_t task);
    private:
        std::vector<task_t> _tasks;
};
void TaskManager::run() {
    for (auto& task : _tasks) {
        task();
    }
}
void TaskManager::addTask(task_t task) {
    _tasks.push_back(task);
}
class Example {
    public:
        Example(){
            taskManager.addTask([this]() {
                task1();
            });
            taskManager.addTask([this,a=int(4)](){
                task2(a);
            });
        }
    TaskManager taskManager;
    private:
        void task1(){ std::cout << "task1!n"; }
        void task2(int a){ std::cout << "task2 says: " << a << "n"; }
};
int main() {
    Example example;
    example.taskManager.run();
}

输出:

task1!
task2 says: 4