How can I pass a member function where a free function is expected?

后端 未结 9 1681
误落风尘
误落风尘 2020-11-22 15:10

The question is the following: consider this piece of code:

#include 


class aClass
{
public:
    void aTest(int a, int b)
    {
        prin         


        
相关标签:
9条回答
  • 2020-11-22 15:24

    @Pete Becker's answer is fine but you can also do it without passing the class instance as an explicit parameter to function1 in C++ 11:

    #include <functional>
    using namespace std::placeholders;
    
    void function1(std::function<void(int, int)> fun)
    {
        fun(1, 1);
    }
    
    int main (int argc, const char * argv[])
    {
       ...
    
       aClass a;
       auto fp = std::bind(&aClass::test, a, _1, _2);
       function1(fp);
    
       return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 15:27

    Not sure why this incredibly simple solution has been passed up:

    #include <stdio.h>
    
    class aClass
    {
    public:
        void aTest(int a, int b)
        {
            printf("%d + %d = %d\n", a, b, a + b);
        }
    };
    
    template<class C>
    void function1(void (C::*function)(int, int), C& c)
    {
        (c.*function)(1, 1);
    }
    void function1(void (*function)(int, int)) {
      function(1, 1);
    }
    
    void test(int a,int b)
    {
        printf("%d - %d = %d\n", a , b , a - b);
    }
    
    int main (int argc, const char* argv[])
    {
        aClass a;
    
        function1(&test);
        function1<aClass>(&aClass::aTest, a);
        return 0;
    }
    

    Output:

    1 - 1 = 0
    1 + 1 = 2
    
    0 讨论(0)
  • 2020-11-22 15:28

    A pointer to member function is different from a pointer to function. In order to use a member function through a pointer you need a pointer to it (obviously ) and an object to apply it to. So the appropriate version of function1 would be

    void function1(void (aClass::*function)(int, int), aClass& a) {
        (a.*function)(1, 1);
    }
    

    and to call it:

    aClass a; // note: no parentheses; with parentheses it's a function declaration
    function1(&aClass::test, a);
    
    0 讨论(0)
  • 2020-11-22 15:28

    Since 2011, if you can change function1, do so, like this:

    #include <functional>
    #include <cstdio>
    
    using namespace std;
    
    class aClass
    {
    public:
        void aTest(int a, int b)
        {
            printf("%d + %d = %d", a, b, a + b);
        }
    };
    
    template <typename Callable>
    void function1(Callable f)
    {
        f(1, 1);
    }
    
    void test(int a,int b)
    {
        printf("%d - %d = %d", a , b , a - b);
    }
    
    int main()
    {
        aClass obj;
    
        // Free function
        function1(&test);
    
        // Bound member function
        using namespace std::placeholders;
        function1(std::bind(&aClass::aTest, obj, _1, _2));
    
        // Lambda
        function1([&](int a, int b) {
            obj.aTest(a, b);
        });
    }
    

    (live demo)

    Notice also that I fixed your broken object definition (aClass a(); declares a function).

    0 讨论(0)
  • 2020-11-22 15:29

    I made the member function as static and all works:

    #include <iostream>
    
    class aClass
    {
    public:
        static void aTest(int a, int b)
        {
            printf("%d + %d = %d\n", a, b, a + b);
        }
    };
    
    void function1(int a,int b,void function(int, int))
    {
        function(a, b);
    }
    
    void test(int a,int b)
    {
        printf("%d - %d = %d\n", a , b , a - b);
    }
    
    int main (int argc, const char* argv[])
    {
        aClass a;
    
        function1(10,12,test);
        function1(10,12,a.aTest); // <-- How should I point to a's aClass::test function?
    
        getchar();return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 15:34

    If you actually don't need to use the instance a (i.e. you can make it static like @mathengineer 's answer) you can simply pass in a non-capture lambda. (which decay to function pointer)


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

    Wandbox


    note: if aClass is costly to construct or has side effect, this may not be a good way.

    0 讨论(0)
提交回复
热议问题