Passing member function pointer to member object in c++

后端 未结 4 1202
一个人的身影
一个人的身影 2020-12-04 22:54

I have a problem with using a pointer to function in C++. Here is my example:

#include 

using namespace std;

class bar
{
public:
    void (         


        
相关标签:
4条回答
  • 2020-12-04 23:08

    To make your second option work, declare foo so the compiler knows that it is a class.

    Also note that your function pointer syntax is incorrect. The * comes just before the name of the variable:

    class foo;
    
    class bar
    {
    public:
        void (foo::*funcP)();
    };
    
    0 讨论(0)
  • 2020-12-04 23:16

    forward foo's declaration in front of bar:

    class foo;
    
    0 讨论(0)
  • 2020-12-04 23:18

    Taking everyone's suggestions together, your final solution will look like:

    #include <iostream> 
    using std::cout;
    usind std::endl;
    
    class foo; // tell the compiler there's a foo out there.
    
    class bar 
    { 
    public: 
        // If you want to store a pointer to each type of function you'll
        // need two different pointers here:
        void (*freeFunctionPointer)();
        void (foo::*memberFunctionPointer)();
    }; 
    
    class foo 
    { 
    public: 
        bar myBar; 
        void hello(){ cout << "hello" << endl; }
    }; 
    
    void byebye() 
    { 
        cout << "bye" << endl; 
    } 
    
    
    int main() 
    { 
        foo testFoo; 
    
        testFoo.myBar.freeFunctionPointer = &byebye;
        testFoo.myBar.memberFunctionPointer = &foo::hello;
    
        ((testFoo).*(testFoo.myBar.memberFunctionPointer))(); // calls foo::hello()
        testFoo.myBar.freeFunctionPointer();   // calls byebye()
        return 0; 
    } 
    

    The C++ FAQ Lite has some guidance on how to simplify the syntax.

    Taking Chris' idea and running with it, you could get yourself something like this:

    #include <iostream>
    using std::cout; using std::endl;
    
    class foo;
    typedef void (*FreeFn)();
    typedef void (foo::*MemberFn)();
    
    class bar
    {
    public:
      bar() : freeFn(NULL), memberFn(NULL) {}
      void operator()(foo* other)
      {
        if (freeFn != NULL) { freeFn(); }
        else if (memberFn != NULL) { ((other)->*(memberFn))(); }
        else { cout << "No function attached!" << endl; }
      }
    
      void setFreeFn(FreeFn value) { freeFn = value; memberFn = NULL; }
      void setMemberFn(MemberFn value) { memberFn = value; freeFn = NULL; }
    private:
      FreeFn freeFn;
      MemberFn memberFn;
    };
    
    class foo
    {
    public:
      bar myBar;
      void hello() { cout << "foo::hello()" << endl; }
      void operator()() { myBar(this); }
    };
    
    void bye() { cout << "bye()" << endl; }
    
    int main()
    {
      foo testFoo;
    
      testFoo();
    
      testFoo.myBar.setMemberFn(&foo::hello);
      testFoo();
    
      testFoo.myBar.setFreeFn(&bye);
      testFoo();
    
      return 0;
    }
    
    0 讨论(0)
  • 2020-12-04 23:26

    As the error says, methods belong to the class, not to individual instances. For this reason pointers to free functions and pointers to non-static methods are completely different things. You'll also need an instance to call the method on.

    //declaring and taking the address of a foo's method 
    void (foo::*method)() = &foo::hello; //as the compiler nicely suggests
    
    //calling a function through pointer
    free_func();
    
    //calling a method through pointer
    foo instance;
    (instance.*method)();
    

    You can use libraries like Boost.Bind and Boost.Function (also in std::tr1 I think) to abstract away the difference and also bind an instance to the method:

    #include <iostream>
    #include <boost/bind.hpp>
    #include <boost/function.hpp>
    
    using namespace std;
    
    class foo
    {
    public:
        void hello(){cout << "hello" << endl;};
    };
    
    void byebye()
    {
        cout << "bye" << endl;
    }
    
    
    int main()
    {
        foo testFoo;
    
        boost::function<void()> helloFunc(boost::bind(&foo::hello, testFoo));
        boost::function<void()> byeFunc(byebye);
    
        helloFunc();
        byeFunc();
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题