如何在需要自由函数的地方传递成员函数?

新手上路,请多包涵

问题如下:考虑这段代码:

 #include <iostream>

class aClass
{
public:
    void aTest(int a, int b)
    {
        printf("%d + %d = %d", a, b, a + b);
    }
};

void function1(void (*function)(int, int))
{
    function(1, 1);
}

void test(int a,int b)
{
    printf("%d - %d = %d", a , b , a - b);
}

int main()
{
    aClass a;

    function1(&test);
    function1(&aClass::aTest); // <-- How should I point to a's aClass::test function?
}

如何使用 aaClass::test 作为 function1 的参数?我想访问班级的成员。

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

阅读 576
2 个回答

使用函数指针没有任何问题。但是,指向非静态成员函数的指针与普通函数指针不同:成员函数需要在作为隐式参数传递给函数的对象上调用。上面的成员函数的签名是,因此

void (aClass::*)(int, int)

而不是您尝试使用的类型

void (*)(int, int)

一种方法可能包括创建成员函数 static 在这种情况下,它不需要调用任何对象,您可以将其与类型一起使用 void (*)(int, int)

如果你需要访问你的类的任何非静态成员 并且 你需要坚持使用函数指针,例如,因为函数是 C 接口的一部分,你最好的选择是总是传递一个 void* 到您的函数采用函数指针并通过转发函数调用您的成员,该函数从 void* 获取对象,然后调用成员函数。

在适当的 C++ 接口中,您可能希望查看让函数为函数对象采用模板化参数以使用任意类类型。如果不希望使用模板化接口,您应该使用类似 std::function<void(int, int)> 的东西:您可以为这些创建适当的可调用函数对象,例如,使用 std::bind()

使用类类型的模板参数或合适的 std::function<...> 的类型安全方法比使用 void* 接口更可取,因为它们消除了由于强制转换为错误而导致错误的可能性类型。

为了阐明如何使用函数指针来调用成员函数,下面是一个示例:

 // the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
    fptr(context, 17, 42);
}

void non_member(void*, int i0, int i1) {
    std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}

struct foo {
    void member(int i0, int i1) {
        std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
    }
};

void forwarder(void* context, int i0, int i1) {
    static_cast<foo*>(context)->member(i0, i1);
}

int main() {
    somefunction(&non_member, nullptr);
    foo object;
    somefunction(&forwarder, &object);
}

原文由 Dietmar Kühl 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您实际上不需要使用实例 a (即您可以像@mathengineer 的 回答 一样使其成为静态),您可以简单地传入一个非捕获 lambda。 (衰减到函数指针)


 #include <iostream>

class aClass
{
public:
   void aTest(int a, int b)
   {
      printf("%d + %d = %d", a, b, a + b);
   }
};

void function1(void (*function)(int, int))
{
    function(1, 1);
}

int main()
{
   //note: you don't need the `+`
   function1(+[](int a,int b){return aClass{}.aTest(a,b);});
}

魔杖盒


注意:如果 aClass 构建成本高或有副作用,这可能不是一个好方法。

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

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