Передать функцию класса другой функции класса

извините за возможные дубликаты, но я не понял примеры и фрагменты кода, которые я нашел.

У меня есть класс с именем «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 ++, поэтому я хочу извиниться, если я делаю какие-то «не-gos» или смешиваю некоторые термины.

Вопрос заключается в следующем: как я могу передать свою функцию класса (функцию-член?) Этой функции setHandleAfterTouch библиотеки?

Это не сработает:

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

… моя IDE говорит

нет соответствующей функции для вызова usb_midi_class: setHandleAfterTouch (void (EncoderWrapper :: *) (byte, byte))

Я также пытался

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

Но это не сработает … и я не понимаю этого.

Каждая помощь очень ценится 😉

0

Решение

Указатель на функцию и указатель на функцию-член имеют разные типы. Вы можете это для себя:

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 функция статическая. Если он статический, его указатель не является указателем на функцию-член, а является обычным указателем на функцию.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]