将 class 函数传递给另一个 class 函数
Pass class function to another class function
抱歉可能重复,但我不理解我找到的示例和代码片段。
我有一个名为 "EncoderWrapper" 的 class,其中包含一些功能。其中一个函数称为 "onAfterTouch" 并在 "EncoderWrapper.h" 文件中声明。
void onAfterTouch(byte channel, byte pressure);
这些函数将成为我使用的库的另一个 class 函数的回调
inline void setHandleAfterTouch(void (*fptr)(uint8_t channel, uint8_t pressure)) {
usb_midi_handleAfterTouch = fptr;
};
注意:我是 C++ 的新手,所以如果我在做一些事情 "no-gos" 或混淆了一些术语,我想说声抱歉。
问题是:如何将我的 class 函数(成员函数?)传递给库的那个 "setHandleAfterTouch" 函数?
这行不通:
void EncoderWrapper::attachMIDIEvents()
{
usbMIDI.setHandleAfterTouch(&EncoderWrapper::onAfterTouch);
}
...我的 IDE 说
no matching function for call usb_midi_class:setHandleAfterTouch(void (EncoderWrapper::*)(byte, byte))
我也试过了
usbMIDI.setHandleAfterTouch((&this->onAfterTouch));
但这行不通……而且我不明白这方面的方法。
非常感谢您的帮助 ;-)
函数指针和成员函数指针有不同的类型。你可以自己做:
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;
};
因为只接受来自一个 class 的函数相当受限,我建议使用 std::function
:
inline void setHandleAfterTouch(std::function<void(uint8_t, uint8_t)> fptr) {
usb_midi_handleAfterTouch = std::move(fptr);
};
这将允许您发送带有捕获的 lambda,并在其中调用您的成员函数:
// 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
函数静态化。如果是静态的,它的指针就不是成员函数指针,而是一个普通的函数指针。
抱歉可能重复,但我不理解我找到的示例和代码片段。
我有一个名为 "EncoderWrapper" 的 class,其中包含一些功能。其中一个函数称为 "onAfterTouch" 并在 "EncoderWrapper.h" 文件中声明。
void onAfterTouch(byte channel, byte pressure);
这些函数将成为我使用的库的另一个 class 函数的回调
inline void setHandleAfterTouch(void (*fptr)(uint8_t channel, uint8_t pressure)) {
usb_midi_handleAfterTouch = fptr;
};
注意:我是 C++ 的新手,所以如果我在做一些事情 "no-gos" 或混淆了一些术语,我想说声抱歉。
问题是:如何将我的 class 函数(成员函数?)传递给库的那个 "setHandleAfterTouch" 函数?
这行不通:
void EncoderWrapper::attachMIDIEvents()
{
usbMIDI.setHandleAfterTouch(&EncoderWrapper::onAfterTouch);
}
...我的 IDE 说
no matching function for call usb_midi_class:setHandleAfterTouch(void (EncoderWrapper::*)(byte, byte))
我也试过了
usbMIDI.setHandleAfterTouch((&this->onAfterTouch));
但这行不通……而且我不明白这方面的方法。
非常感谢您的帮助 ;-)
函数指针和成员函数指针有不同的类型。你可以自己做:
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;
};
因为只接受来自一个 class 的函数相当受限,我建议使用 std::function
:
inline void setHandleAfterTouch(std::function<void(uint8_t, uint8_t)> fptr) {
usb_midi_handleAfterTouch = std::move(fptr);
};
这将允许您发送带有捕获的 lambda,并在其中调用您的成员函数:
// 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
函数静态化。如果是静态的,它的指针就不是成员函数指针,而是一个普通的函数指针。