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

Posted

技术标签:

【中文标题】C++ 指向具有匹配函数签名的任何类的成员函数的指针【英文标题】:C++ Pointer to a member function of any class with matching function signatures 【发布时间】:2016-04-09 06:30:44 【问题描述】:

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

我可以借助 C++ 标准库中的 std::function 来做到这一点。我也一直使用常规的 C 函数来执行此操作,而 std 库没有帮助。我正在编写固件,代码空间有限。如果来自 C++ 标准库的助手可以做到这一点,那么肯定可以使用纯 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


【问题讨论】:

首先A a(); 是错误的。这是声明一个函数a ping_event = a.ping_event_handler; - 编译器如何知道给this 提供什么值? 考虑将这些方法声明为静态(如果它们不需要对象的状态)或虚拟(从公共基类继承),并将指向函数的指针替换为指向基类的指针.如果你想混合指向函数的指针和指向方法的指针,那么你需要一些包装器作为 std:function。 我认为你不能使用函数指针来做到这一点。 void (*ping_event)(); 是指向普通函数的指针,不能用它指向类成员函数,即 void (A::*ping_event)() ;对于 A 类void (B::*ping_event)(); B类。使成员函数静态将与您的函数指针一起使用。 @bkVnet 基类的东西可以工作,不能使用std-lib,并且不想被限制在静态函数中。我不想为了让我的对象能够处理事件/信号而不得不进行子类化。问题似乎是编译器使用 Class 类型作为函数签名的一部分,使其无法独立于类。但是如果std::function 可以做到这一点,那么如果我有一个带有签名的指针和一个指向其中一个对象的指针,那么我必须有一种方法可以调用成员函数。我觉得会涉及到选角。 【参考方案1】:

老办法是用函数传递userData

void (*ping_event)(void* userData);

并保存函数和用户数据。 然后在用户端,在它的类中转换 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();

Demo

【讨论】:

干得好!完美运行,没有标准库或子类化。您能否在参数中包含函数调用的外观,以供参考。还是那不可能? 你要改函数指针类型,改函数调用:Demo

以上是关于C++ 指向具有匹配函数签名的任何类的成员函数的指针的主要内容,如果未能解决你的问题,请参考以下文章

虚函数的调用

C++|详解类成员指针:数据成员指针和成员函数指针及应用场合

使用成员函数求解方程 C++

如何创建一个存储指向成员函数的指针的类 (C++)

在 C++ 中将指向基类的指针传递给派生类的成员函数

将任何类的任何成员函数作为回调函数传递