C++中類成員函數作爲回調函數的幾種方法

寫了一個C++小遊戲,想法是間接別人的C語言,但是真正自己操作起來,還是會遇到各種問題,同時也讓自己更真切的學到了一些過眼即忘,只有親自動手才能學到的知識。

如何實現C++中的成員作爲回調函數?這是我遇到的最大的問題:

當你調用signal()時需要一個void(*)(int)的函數指針,當你調用pthread_create()時你需要一個(void *)(*)(void *)的函數指針,這時如果你需要使一個非靜態成員函數作爲回調函數的話,是不會被編譯器同通過的。以上篇blog中的情景爲例,成員函數moveSnake的函數指針類型真正爲void(Snake::*)(),不是你想要的。這時可以:

1)如果這個函數是非靜態成員函數,而且可以從類中提到類外,作爲一個普通函數,這樣就可以以正常的函數指針調用了。

2)如果這個函數是靜態成員函數,那麼不需要任何轉換,因爲靜態成員函數不屬於任何對象,它本身就是一個普通函數指針。

3)如果這個函數不操作任何非靜態的數據成員,那麼就可以加static使之變成靜態成員函數,此例中由於moveSnake需要操作數據成員,所以這種方法此處不同。

4)通過一個友元函數,加一個間接層解決問題,具體參見blog.sina.com.cn/s/blog_4298002e0100euh8.html

5)通過boost::function和boost::bind,這個可以達到調用成員函數的目的,並不能解決此處的問題,因爲最後function<void(int)>無法轉換成void(*)(int)。具體可以參見stackoverflow.com/questions/3381829/how-do-i-implement-a-callback-in-c

boost::function<void()> callback;
Target myTarget;
callback=boost::bind(&Target::doSomething,&myTarget);

callback(); // calls the function
6)通過強制轉換
#include <pthread.h>
#include <iostream>
using namespace std;
class MyClass
{
   pthread_t tid;
   void func()
   {
      cout<<"強制轉換";    
   }
public:
   bool startThread()
   {
      typedef void* (*FUNC)(void*);//定義FUNC類型是一個指向函數的指針
      FUNC callback = (FUNC)&MyClass::func;//強制轉換func()的類型
      int ret = pthread_create( &tid , NULL , callback , this );
      if( ret != 0 )
          return false;
      else
          return true;
   }
};
int main()
{
   MyClass myClass;
   myClass.startThread();
}
7)也是通過加一個間接層,包裝真正的信號處理函數即可,即上一篇文中解決文題用到的方法。
#include <signal.h>
#include <unistd.h>
#include <iostream>
using namespace std;
class Fred {
public:
  void memberFn(){
  }
  static void staticMemberFn(int x){}  // A static member function can usually handle it
};
      // Wrapper function uses a global to remember the object:
Fred object_which_will_handle_signal;
    
void Fred_memberFn_wrapper(int)
{
    object_which_will_handle_signal.memberFn();
}
      
int main()
{
  /* signal(SIGINT, Fred::memberFn); */   // Can NOT do this
   signal(SIGALRM, Fred_memberFn_wrapper);  // OK
   signal(SIGINT, Fred::staticMemberFn);   // OK usually; see below
}
普通的C++成員函數都隱含了一個傳遞函數作爲參數,亦即“this”指針,C++通過傳遞一個指向自身的指針給其成員函數從而實現程序函數可以訪問C++的數據成員。普通成員函數
屬於類的對象,對象可以有許多個,這樣編譯器就不知到綁定到哪個地址了。而static成員函數屬於類,只有一個實例,就可以作爲普通函數指針使用。 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章