как отправить адрес функции из класса1 в класс2 - PullRequest
0 голосов
/ 03 января 2019

c ++ 11 / arm compiler v6.9 / keil5

У меня есть 2 класса (class1, class2) - я хочу отправить адрес функции из класса 1 в класс 2, но я не могу - я должен определитьмоя функция статическая - но я не хочу делать это

// ---------------------------- CLASS1.CPP ----------------------------
void CLASS1::ControlTransfer(uint8_t Physical_EPn, uint8_t bEPStatus) {
 // ...
}

void CLASS1::init() {
    class2.intHandler(2, ControlTransfer); // error: reference to non-static member function must be called
}

// ---------------------------- CLASS2.H ----------------------------
typedef void (TFnEPIntHandler)  (uint8_t Physical_EPn, uint8_t bEPStatus);

// ---------------------------- CLASS2.CPP ----------------------------
TFnEPIntHandler *_apfnEPIntHandlers[16];

void CLASS2::intHandler( uint8_t num, TFnEPIntHandler *pfnHandler ) {
    _apfnEPIntHandlers[ num ] = pfnHandler;
}

// _apfnEPIntHandlers used in my interrupt function

1 Ответ

0 голосов
/ 03 января 2019

Нестатическая функция-член, такая как CLASS1::ControlTransfer, не может быть вызвана, не зная, какой объект CLASS1 будет вызывать ее.А необработанный указатель на функцию, подобную вашей TFnEPIntHandler, просто не содержит достаточно информации для указания этого объекта.

Если вы можете, рассмотрите возможность изменения необработанных указателей на функции на более гибкий тип std::function:

// In a header file:
#include <functional>
using TFnEPIntHandler = std::function<void(uint8_t, uint8_t)>;

// TFnEPIntHandler should now be used directly, not as a pointer.
// (Note a std::function can "act like" a null pointer.)
TFnEPIntHandler _apfnEPIntHandlers[16];
void CLASS2::intHandler( uint8_t num, TFnEPIntHandler pfnHandler ) {
    _apfnEPIntHandlers[ num ] = std::move(pfnHandler);
}

// Replace CLASS1::init():
void CLASS1::init() {
    // Use a lambda which captures the "this" pointer and can be
    // converted to the std::function type.  The function must not
    // be used after this CLASS1 object is destroyed!
    class2.intHandler(2, [this](uint8_t Physical_EPn, uint8_t bEPStatus)
        { ControlTransfer(Physical_EPn, bEPStatus); });
}

Если std::function не является опцией, потому что вам нужно взаимодействовать с кодом C, вы можете добавить дополнительный тип void* к типу функции и использовать функции-оболочки, которые приводят этот указатель к типу классавызвать реальную нестатическую функцию-член.Например:

class CLASS1 {
// ...
private:
    static void ControlTransferCB(uint8_t Physical_EPn,
                                  uint8_t bEPStatus,
                                  void* extra)
    {
        static_cast<CLASS1*>(extra)->ControlTransfer(Physical_EPn, bEPStatus);
    }
// ...
};

Дополнительный аргумент void* может быть предоставлен CLASS2::intHandler (что подразумевает наличие массива структур указателей функций и дополнительных данных void*) или другой логикекоторый на самом деле вызывает функции, в зависимости от того, что больше подходит.

...