2011-07-27 27 views
2

我想用C++實現一個觀察者模式(各種),並且我想使用函數指針來這樣做,但是在嘗試投射時我不斷收到錯誤從B類函數指針到一個typedef函數指針:如何使用typedef函數指針來註冊回調

#include <map> 

typedef int (*OutputEvent)(const char*, const char*, int); 

class A 
{ 
private: 
    int nextListenerId; 
    std::map<int, OutputEvent> listenerMap; 
public: 
    A(){ nextListenerId = 0;} 
    ~A(){} 
    inline int RegisterListener(OutputEvent callback) 
    { 
     nextListenerId++; 
     listenerMap[nextListenerId] = callback; 
     return nextListenerId; 
    } 
}; 

class B 
{ 
private: 
    int listenerId; 
public: 
    B(const A& a) 
    { 
     OutputEvent e = &B::CallMeBack; 
     listenerId = a.RegisterListener(e); 
    } 
    ~B(){} 

    int CallMeBack(const char* x, const char* y, int z) 
    { 
     return 0; 
    } 
}; 

我創造了這個例子,我已經pasted it into codepad.org,但是當我編譯失敗(不編譯codepad.org也不在Visual Studio 2010):

Output: 

t.cpp: In constructor 'B::B(const A&)': 
Line 28: error: cannot convert 'int (B::*)(const char*, const char*, int)' to 'int (*)(const char*, const char*, int)' in initialization 
compilation terminated due to -Wfatal-errors. 

我不明白爲什麼它不能轉換功能n個指針。請有人幫助我嗎?

+1

這已被問了很多次:http://stackoverflow.com/questions/4210710/cast-pointer-to-member-function-to-normal-pointer和更多。另見http://www.parashift.com/c++-faq-lite/pointers-to-members.html。 –

+0

參見http://stackoverflow.com/questions/1151582/pthread-function-from-a-class。 –

回答

1

您試圖投射到OutputEvent的功能是成員函數。這是通過這顯然是錯誤消息表示:

'int (B::*)(const char*, const char*, int)' 

這是一種不同的類型

int (*OutputEvent)(const char*, const char*, int) 
因爲 B::部分的

(這意味着該函數有一個看不見的this參數)。

如果你定義成員函數爲靜態的,那麼你就可以將它轉換爲OutputEvent

class B 
{ 
    .... 
    static int CallMeBack(const char* x, const char* y, int z); 
    ... 
}; 
+0

好吧,那麼我想我的解決方案是真正實現觀察者模式,並有兩種類型的觀察者:'B'將實現Observer'接口,如果有人想使用OutputEvent函數指針,那麼他們將使用一個類'C',它在構造函數中使用該OutputEvent函數指針('C'也會實現'Observer'接口)。這樣我可以回調成員函數,靜態函數或全局函數(???)。 – Kiril

0

成員函數與typedef'd原型不匹配,因爲成員函數具有不可見的「this」參數。使其成爲一個靜態函數,它應該工作。

0

類的成員函數有一個隱藏的參數,對象,其全球功能不有。

做這樣的事情: -

B*pB; 

int CallMeBack(const char* x, const char* y, int z) 
{ 
    return pB->CallMeBack(x,y,z); 
} 

,如果你有在同一時間外出幾個回調更加困難。但是,如果只有一個,你可以有一個指向該對象的指針並通過它調用。