2011-01-29 20 views
0

所以我有這樣一個類:在一個類中有「typedef void FuncCharPtr」如何提供使用非靜態函數的typedef函數?

class IGraphElement{ 

    // We should define prototype of functions that will be subscribers to our data 
    typedef void FuncCharPtr(char*, int) ; 

public: 
    // Function for adding subscribers functions 
    void Add(FuncCharPtr* f) 
    { 
      //... 
    } 
}; 

和其他類一樣

#include "IGraphElement.h" 

class simpleRendererGraphElement : public IGraphElement 
{ 
    public: 
    IGraphElement* charGenerator; 
    // we owerrite init 
    void Init(IGraphElement* CharGenerator) 
    { 
     charGenerator = CharGenerator; 
     //we can to subscribe some function to our data generator 
     charGenerator->Add(renderCastedData); // and here we receive C3867 
    } 
    void renderCastedData(char* castedChar, int castedCharLength) // our event system receives functions declared like void FuncCharPtr(char*, int) ; 
    { } 
}; 

我們爲什麼錯誤C3867以及如何解決它沒有制定職能靜態的?

+0

'FuncCharPtr'是一個誤稱:它根本不是一個指針類型,它是一個函數類型。指針類型看起來像'typedef void(* FuncCharPtr)(char *,int);'。 –

回答

1

renderCastedData是一個非靜態成員函數。它的類型是

void (simpleRendererGraphElement::*)(char*, int) 

爲了調用它,你需要有simpleRendererGraphElement實例爲this參數。這個問題有很多解決方案。一種選擇是使Add一個函數模板,它需要什麼,可以用char*int參數來調用:

template <typename Function> 
void Add(Function f) 

,那麼你可以寫一個函數對象來包裝呼叫:

struct RenderCastedDataFunctor 
{ 
    simpleRendererGraphElement* obj_; 

    RenderCastedDataFunctor(simpleRendererGraphElement* obj) 
     : obj_(obj) { } 

    void operator()(char* castedChar, int castedCharLength) 
    { 
     obj_->renderCastedData(castedChar, castedCharLength); 
    } 
}; 

並從Init功能,您可以撥打

charGenerator->Add(RenderCastedDataFunctor(this)); 

(該bind和0123來自Boost,C++ TR1和C++ 0x的庫提供了此模式的一般形式,允許您將參數綁定到任何可調用實體並存儲這些綁定可調用實體以供以後使用。這裏這種特殊的方法只是一種簡單化的版本,應該沒有任何額外的或可能不支持庫工作。)

+0

它不會工作在添加模板之後出RenderCastedDataFunctor?我們可以指定我們的模板功能輸入嗎? – Rella

1
typedef void FuncCharPtr(char*, int) ; 

首先,上述應該是這樣,

typedef void (*FuncCharPtr)(char*, int) ; 

其次,renderCastedData不是一個函數指針;它是成員函數指針。所以有區別。它的類型是void (simpleRendererGraphElement::*)(char*, int);,不是上述類型!

+0

@Downvoter:謹慎解釋原因? – Nawaz

+0

我不是投票人 - 我投了票。我有一個問題 - 如何使typedef成爲一個模板,以便任何需要(char *,int)參數的指針類型都是「可添加的」? – Rella

+0

@Kabumbus:你不能寫泛型typedef。這不被允許。但不用擔心,你有更好的解決方案:你可以寫通用仿函數來實現相同的功能! – Nawaz

1

的成員函數是不是一個普通的功能,並且不能被分配到一個普通函數指針。

使用靜態成員函數,如果renderCastedData需要不被綁定到任何類的實例。

如果renderCastedData必須綁定到一個類實例,讓IGraphElement::Add接受一個成員函數指針和一個指向類的指針。

的boost ::功能和boost ::綁定也是問題的一個很好的選擇,他們提供更多的flexbility,但有時也可以是一個慢一點。