2017-08-20 44 views
0

對不起,可能的重複,但我不明白我找到了例子和代碼片斷。通行證類函數到另一個類的功能

我有一個名爲「EncoderWrapper」,其中包括一些功能類。其中一個函數稱爲「onAfterTouch」,並在「EncoderWrapper.h」文件中聲明。

void onAfterTouch(byte channel, byte pressure); 

的功能將成爲圖書館的其他類功能的回調我用

inline void setHandleAfterTouch(void (*fptr)(uint8_t channel, uint8_t pressure)) {     
    usb_midi_handleAfterTouch = fptr; 
}; 

注:我完全新的C++,所以我想說對不起,如果我做一些「no-gos」或混合了一些術語。

的問題是:如何通過我的類函數(成員函數?)到庫說,「setHandleAfterTouch」功能?

這是行不通的:

void EncoderWrapper::attachMIDIEvents() 
{ 
    usbMIDI.setHandleAfterTouch(&EncoderWrapper::onAfterTouch); 
} 

...我的IDE說

呼叫usb_midi_class沒有匹配功能:setHandleAfterTouch(無效(EncoderWrapper :: *)(字節,字節) )

我也試過

usbMIDI.setHandleAfterTouch((&this->onAfterTouch)); 

但是這不會工作...我沒有得到有關的做法。

每個幫助都非常感謝;-)

回答

1

函數指針和成員函數指針有不同的類型。你可以把它自己:

struct Test { 
    void fun(); 
}; 

int main() { 
    void(*ptr)() = &Test::fun; // error! 
} 

相反,成員函數指針需要這句法:

void(Test::*fun)() = &Test::fun; // works! 

你問爲什麼?因爲成員函數需要一個實例來調用。並調用函數有一個特殊的語法太:

Test t; 

(t.*funptr)(); 

要接受成員函數的指針,你需要你的代碼改成這樣:

inline void setHandleAfterTouch(void(EncodeWrapper::*fptr)(uint8_t, uint8_t)) {     
    usb_midi_handleAfterTouch = fptr; 
}; 

,因爲它是太有限了只接受來自功能一個班,我推薦使用std::function

inline void setHandleAfterTouch(std::function<void(uint8_t, uint8_t)> fptr) {     
    usb_midi_handleAfterTouch = std::move(fptr); 
}; 

這將讓你與捕獲發送拉姆達,並打電話給你的成員函數insode它:

// we capture this to use member function inside 
//       v--- 
usbMIDI.setHandleAfterTouch([this](uint8_t, channel, uint8_t pressure) { 
    onAfterTouch(channel, pressure); 
}); 

看來你不能改變,並通過在API快速查找,它似乎沒有可以訪問的狀態對象。

在這種情況下,如果你想使用你的成員函數,你需要引入一個全局狀態:

// global variable 
EncodeWrapper* encode = nullptr; 

// in your function that sets the handle 
encode = this; //   v--- No capture makes it convertible to a function pointer 
usbMIDI.setHandleAfterTouch([](uint8_t, channel, uint8_t pressure) { 
    encode->onAfterTouch(channel, pressure); 
}); 

另一種解決方案是使onAfterTouch功能靜態的。如果它是靜態的,它的指針不是成員函數指針,而是一個正常的函數指針。

+0

嗨Guillaume, 謝謝你的回覆。我想我明白了,但我不能修改setHandleAfterTouch函數,因爲它包含在庫中... 目前聽起來像我不能在我的類中使用該庫? https://www.pjrc.com/teensy/td_midi.html –

+0

或者我應該爲usbMIDI實例添加一個getter,併爲每個回調添加一個getter。而且,在我實例化封裝類之後,我應該在該實例上使用getter並設置回調函數? –

+0

@ pixel-shock看看我的編輯 –