Class member function pointer

后端 未结 3 1365
抹茶落季
抹茶落季 2020-12-13 16:25

I\'m trying to use a class function (interrupt service routine),

void (ClassName::*fp)(void)=ClassName::FunctionName;

and attaching it to a

相关标签:
3条回答
  • 2020-12-13 16:56

    Each class member function has an implicit first parameter that is the this pointer, so your method in fact is not with void paramter list - it takes one parameter-- the instance it is invoked on.

    0 讨论(0)
  • 2020-12-13 17:03

    You can use boost::function<> or boost::bind<> to point to a class member function:

    # include <boost/function.hpp>
    # include <boost/bind.hpp>
    class FunctionClass {
        private:
           double a_;
        public:
           FunctionClass (const double & a): a_(a ){}
           double multWithA (const double & x) const { return a_*x;}
           double operator ()(const double & x) const { return a_*x;}
    };
    
    FunctionClass myClass (2.0);
    double x = 12.0;
    boost :: function <double (FunctionClass *, double)> funcPtr , funcPtr1;
    funcPtr =& FunctionClass :: multWithA;
    funcPtr1 =& FunctionClass :: operator ();
    
    std :: cout << myClass . multWithA (x) << std :: endl;
    std :: cout << funcPtr (& myClass ,x) << std :: endl;
    std :: cout << funcPtr1 (& myClass ,x) << std :: endl;
    
    // Bind the function with the class instance
    boost :: function <double (double)> funcPtrNew ;
    funcPtrNew = boost :: bind (funcPtr ,& myClass ,_1);
    std :: cout << funcPtrNew (x) << std :: endl;
    
    0 讨论(0)
  • 2020-12-13 17:13

    If the function is not static, you cannot pass it in input to a function that accepts a non-member function pointer.

    Consider that a non-static member function has an implicit pointer to ClassName as its first parameter, which points to the object on which the member function is being invoked.

    struct X
    {
        static void foo() { } // Does not have an implicit "this" pointer argument
        void bar() { } // Has an implicit "this" pointer argument
    };
    
    int main()
    {
        void (*f)() = &X::foo; // OK: foo is static
        void (*g)() = &X::bar; // ERROR! bar is non-static
    }
    

    Here, not even std::bind() will work, because the result is not convertible to a function pointer. Lambdas are convertible to function pointers, but only if they are non-capturing (and a lambda here would need to capture the object to invoke the member function on).

    Therefore, the only (ugly) workaround is to have a global adapter function which invokes the member function on an object which is available through a global pointer variable. The global pointer variable is set prior to calling the function:

    struct X
    {
        void bar() { }
    };
    
    void function_taking_a_function_pointer(void (*f)())
    {
        // Do something...
        f();
    }
    
    X* pX = nullptr;
    void bar_adapter()
    {
        pX->bar();
    }
    
    int main()
    {
        X x; // Some object I want to invoke the member function bar() on...
    
        pX = &x; // Set the global pointer and invoke the function...
        function_taking_a_function_pointer(bar_adapter);
    }
    

    If you want, you can make this slightly more flexible by turning bar_adapter into a function template, and passing the pointer-to-member-function as a template argument:

    template<typename T, void (T::*mf)()>
    void adapter()
    {
        (pX->*mf)();
    }
    

    Here is how you would use it:

    #include <iostream>
    
    struct X
    {
        void foo() { std::cout << "X::foo()" << std::endl; }
        void bar() { std::cout << "X::bar()" << std::endl; }
    };
    
    void function_taking_a_function_pointer(void (*f)())
    {
        // Do something...
        f();
    }
    
    X* pX = nullptr;
    
    template<typename T, void (T::*mf)()>
    void adapter()
    {
        (pX->*mf)();
    }
    
    int main()
    {
        X x; // Some object I want to invoke the member function bar() on...
    
        pX = &x; // Set the global pointer and invoke the function(s)...
    
        function_taking_a_function_pointer(adapter<X, &X::foo>);
        function_taking_a_function_pointer(adapter<X, &X::bar>);
    }
    

    Finally, here is a live example.

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