2012-06-25 122 views
1

這裏有很多例子,但我似乎無法弄清楚我的問題的解決方案。我有傳遞成員函數的指針

class FooSource{ 
    ... 

    void StartGetFoos(void (*callback)(vector<IFoo*>*, IAsyncResult)); 
    ... 
} 

StartGetFoos()被調用,它做得到FOOS,節約了回調的請求。當請求完成(大約需要30秒)時,保存的回調將被調用並返回結果。 我無法更改此方法的簽名。

和其他地方我有一個類

class FooUser { 
    ... 

    void FooUser::MyCallback(vector<IFoo*>* foos, IAsyncResult result) 
    { 
      // marshall to UI thread and update UI 
    } 

    void init() 
    { 
     fooUser->StartGetFoos(??????); 
     // how do I pass my callback member function here? 
    } 
} 
+0

相關:http://stackoverflow.com/questions/1738313/c-using-class-method-as-a-function-pointer-type –

回答

3

有無處上的簽名void (*callback)(vector<IFoo*>*, IAsyncResult)爲您收到一個this指針,所以你不能用一個成員函數。相反,你將不得不使用一個static成員函數:

class FooUser { 
    static void MyCallback(vector<IFoo*>* foos, IAsyncResult result) 
    { 
      // marshall to UI thread and update UI 
    } 

    void init() 
    { 
     fooUser->StartGetFoos(&FooUser::MyCallback); 
    } 
}; 

這裏的問題是,你將無法訪問任何FooUser實例數據;這可能是也可能不是問題。

根據API的設計有多好,可能有一種方法來傳遞實例指針,例如,通過IAsyncResult result

+0

你能如何在使用靜態成員函數展開這個案例?我剛纔在看[這篇文章](http://stackoverflow.com/questions/400257/how-can-i-pass-a-class-member-function-as-a-callback),看起來很有前途,但我不能不會爲我的情況改變事情。謝謝您的幫助。 –

+1

@ProfessorChaos,使用靜態成員函數調用另一個非靜態成員函數。要做到這一點,靜態函數需要從某處獲取對象指針,如果永遠不會有多個回調未完成,那麼可能是靜態成員指針變量。 –

2

如果IAsyncResult是傳入的數據結構,然後再次返回操作,則可以使用自己的信息對其進行擴展。

class MyAsyncResult : public IAsyncResult 
{ 
public: 
    MyAsyncResult(FoorUser *sender) : sender(sender){} 
    FooUser *sender; 
}; 

然後,ecatmur說,你可以指定回調的靜態成員函數,但你也可以使被後記稱爲普通成員函數:

靜態成員函數具有非訪問類成員,但可以指定爲通常需要普通C函數的回調。

class FooUser 
{ 
    // static with no access to class members, but can be specified as a callback. 
    static void MyCallback(vector<IFoo*>* foos, IAsyncResult *result) 
    { 
      MyAsyncResult *res = (MyAsyncResult*)result; 
      res->sender->MyCallback(foos, result); 
    } 

    void MyCallback(vector<IFoo*>* foos, IAsyncResult *result) 
    { 
      // handle the actual callback here 
    } 

    void init() 
    { 
     IAsyncResult *res = new MyAsyncResult(this); 
     fooUser->StartGetFoos(&foos, res); 
    } 
}