抱歉可能有重复,但我不明白我找到的示例和代码片段。
我有一个名为“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(void(EncoderWrapper :: *)(byte,byte))
我也试过
usbMIDI.setHandleAfterTouch((&this->onAfterTouch));
但是这不起作用......我没有采用这种方法。
非常感谢每一个帮助; - )
答案 0 :(得分: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);
};
这将允许您发送带捕获的lambda,并调用您的成员函数insode it:
// 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
函数设为静态。如果它是静态的,它的指针不是成员函数指针,而是普通的函数指针。