Why would one use function pointers to member meth

2020-06-05 01:22发布

A lot of C++ books and tutorials explain how to do this, but I haven't seen one that gives a convincing reason to choose to do this.

I understand very well why function pointers were necessary in C (e.g., when using some POSIX facilities). However, AFAIK you can't send them a member function because of the "this" parameter. But if you're already using classes and objects, why not just use an object oriented solution like functors?

Real world examples of where you had to use such function pointers would be appreciated.

Update: I appreciate everyone's answers. I have to say, though, that none of these examples really convinces me that this is a valid mechanism from a pure-OO perspective...

10条回答
劫难
2楼-- · 2020-06-05 01:52

I have some code I'm working on right now where I used them to implement a state machine. The dereferenced member functions implement the states, but since they are all in the class they get to share a certian amount of data that is global to the entire state machine. That would have been tough to accomplish with normal (non-member) function pointers.

I'm still undecided on if this is a good way to implement a state machine though.

查看更多
够拽才男人
3楼-- · 2020-06-05 01:55

You asked specifically about member functions, but there are other uses for function pointers as well. The most common reason why I need to use function pointers in C++ is when I want to load a DLL ar runtime using LoadLibrary(). This is in Windows, obviously. In applications that use plugins in the form of optional DLLs, dynamic linking can't be used at application startup since the DLL will often not be present, and using delayload is a pain.

After loading the library, you have to get a pointer to the functions you want to use.

查看更多
不美不萌又怎样
4楼-- · 2020-06-05 01:56

It is like using lambdas. You always can pass all necessary local variables to a simple function, but sometimes you have to pass more then one of them.

So using member functions will save you from passing all necessary member fields to a functor. That's all.

查看更多
祖国的老花朵
5楼-- · 2020-06-05 01:56

I have used member function pointers parsing a file. Depending on specific strings found in the file the same value was found in a map and the associated function called. This was instead of a large if..else if..else statement comparing strings.

查看更多
ゆ 、 Hurt°
6楼-- · 2020-06-05 01:58

Here is a typical scenario we have here. We have a notification framework, where a class can register to multiple different notifications. When registering to a notification, we pass the member function pointer. This is actually very similar to C# events.

class MyClass
{
    MyClass()
    {
        NotificationMgr::Register( FunctionPtr( this, OnNotification ) );
    }
    ~MyClass()
    {
        NotificationMgr::UnRegister( FunctionPtr( this, OnNotification ) );
    }

    void OnNotification( ... )
    {
        // handle notification
    }
};
查看更多
ゆ 、 Hurt°
7楼-- · 2020-06-05 01:59

The single most important use of member pointers is creating functors. The good news is that you hardly even need to use it directly, as it is already solved in libraries as boost::bind, but you do have to pass the pointers to those libs.

class Processor
{
public:
   void operation( int value );
   void another_operation( int value );
};
int main()
{
   Processor tc;
   boost::thread thr1( boost::bind( &Processor::operation, &tc, 100 ) );
   boost::thread thr2( boost::bind( &Processor::another_operation, &tc, 5 ) );
   thr1.join();
   thr2.join();
}

You can see the simplicity of creating a thread that executes a given operation on a given instance of a class.

The simple handmade approach to the problem above would be on the line of creating a functor yourself:

class functor1
{
public:
    functor1( Processor& o, int v ) : o_(o), v_(v) {}
    void operator()() {
        o_.operation( v_ ); // [1]
    }
private:
    Processor& o_;
    int v_;
};

and create a different one for each member function you wish to call. Note that the functor is exactly the same for operation and for another_operation, but the call in [1] would have to be replicated in both functors. Using a member function pointer you can write a simple functor:

class functor
{
public:
   functor( void (*Processor::member)(int), Processor& p, int value )
      : member_( member ), processor_(p), value_( value ) {}

   void operator()() {
      p.*member(value_);
   }
private:
   void (*Processor::member_)(int);
   Processor& processor_;
   int value;
};

and use it:

int main() {
   Processor p;
   boost::thread thr1( functor( &Processor::operation, p, 100 ) );
   boost::thread thr2( functor( &Processor::another_operation, p, 5 ) );
   thr1.join();
   thr2.join();
}

Then again, you don't need to even define that functor as boost::bind does it for you. The upcoming standard will have its own version of bind along the lines of boost's implementation.

查看更多
登录 后发表回答