指向任何具有匹配函数签名的类的成员函数的C++指针

C++ Pointer to a member function of any class with matching function signatures

本文关键字:函数 成员 C++ 指针 任何具      更新时间:2023-10-16

如何将具有相同签名但来自不同类的非静态成员函数的引用分配给具有匹配签名的函数指针?

我可以在C++std库的std::function的帮助下完成这项工作。我也一直用常规的C函数来做这件事,而没有来自std库的帮助。我正在写固件和代码空间是有限的。如果C++std库中的助手能够做到这一点,那么肯定可以使用纯C/C++语言构造手动完成(首选C++11之前的版本)。

演示我意图的示例代码:

class A {
public:
    void ping_event_handler();
};
class B {
public:
    void ping_event_handler();
};
void A::ping_event_handler_A() {
    // Handle ping event in A...
}
void B::ping_event_handler_B() {
    // Handle ping event in B...
}
void ping_event_handler_C() {
    // Handle ping event in normal function...
}
int main() {
    // Ping event "pointer to a function that takes no arguments"
    void (*ping_event)();
    A a();
    B b();
    ping_event = a.ping_event_handler; // Attach class A's handler
    ping_event();                      // Trigger event
    ping_event = b.ping_event_handler; // Attach class B's handler
    ping_event();                      // Trigger event
    ping_event = ping_event_handler;   // Attach non-class handler
    ping_event();                      // Trigger event
}

旧方法是通过函数传递userData

void (*ping_event)(void* userData);

并保存函数和userData。然后在用户端,在it类中投射userData,并从中调用任何方法:

struct my_function
{
    my_function(void (*f)(void*), void* userData) : mF(f), mUserData(userData)
    {}
    void set(void (*f)(void*), void* userData)
    {
         mF = f;
         mUserData = userData;
    }
    void operator() () {
        mF(mUserData);
    }
    void (*mF)(void*);
    void* mUserData;
};

在呼叫现场:

template <typename C, void (C::*m)()>
void my_func_helper(void* userData)
{
    C* c = static_cast<C*>(userData);
    (c->*m)();
}

int main()
{
    A a;
    my_function f(&my_func_helper<A, &A::ping_event_handler>, &a);
    f();
    B b;
    f.set(&my_func_helper<B, &B::ping_event_handler>, &b);
    f();
    f.set(ping_event_handler_c, NULL);
    f();
}

演示