Получение указателя функции на нестатическую функцию-член

Предположим, у меня есть класс:

class A {
public:
    A(); 
    void myFunc();
};

Затем в другом месте программы я создаю экземпляр класса A и пытаюсь получить указатель функции на myFunc():

A* a = new A;

//ATTEMPTS AT RETRIVING FUNCTION POINTER FOR A::MYFUNC

std::function<void()> fnptr = a->myFunc;

std::function<void()> fnptr(std::bind(A::myFunc, &a);

Но обе эти попытки представляют собой вызов ошибки нестатической функции-члена без объектного аргумента.

Возможно, обе эти попытки совершенно неуместны, но, по сути, я пытаюсь получить указатель функции на функцию myFunc() в конкретном экземпляре a. Любая помощь в том, как это сделать, приветствуется :)


person jf192210    schedule 21.08.2020    source источник
comment
В std::bind(A::myFunc, &a a уже есть указатель. Нет необходимости в другом уровне косвенности. Обратите внимание на лямбда-выражения как на более эффективную альтернативу bind.   -  person user4581301    schedule 21.08.2020


Ответы (2)


Вам нужен следующий синтаксис:

std::function<void()> fnptr(std::bind(&A::myFunc, a));

Вы также можете использовать такое лямбда-выражение:

auto fn = [a] { a->myFunc(); };

Вот демонстрация.

person cigien    schedule 21.08.2020
comment
Большое спасибо, эта лямбда - идеальная реализация. Возможно, только одно дополнение: если я затем захочу передать этот указатель функции функции fnPtrHandler, как будет выглядеть прототип для fnPtrHandler? - person jf192210; 21.08.2020
comment
Если вы хотите передать это функции, сигнатура будет void f(void (A::*)());. Конечно, вы можете передать std::function<void()> или просто сделать f шаблоном. - person cigien; 21.08.2020

Я пытаюсь получить указатель функции на функцию myFunc()

Получить указатель на функцию-член для A::myFunc() можно так:

void (A::*memFuncPtr)() = &A::myFunc;

или даже лучше, воспользовавшись auto:

auto memFuncPtr = &A::myFunc;

Однако для разыменования этого указателя (т. е. для вызова функции-члена, на которую он указывает) вам в конечном итоге понадобится объект A. Этот объект соответствует тому, для которого будет вызываться функция-член.

Вы можете разыменовать указатель на функцию-член memFuncPtr либо в сочетании с объектом A и оператором .*:

A a;
a.*memFuncPtr();

или в сочетании с указателем на объект A и оператором ->*:

A *aPtr = new A();
aPtr->*memFuncPtr();

В результате вам нужно будет сохранить ссылку на объект или его копию, чтобы создать std::function<void()> из этого указателя на функцию-член.

std::invoke

Начиная с C++17, вы можете просто использовать шаблон функции std::invoke(). вместо .*/->*. Он объединяет синтаксис для двух описанных выше случаев:

std::invoke(memFuncPtr, a);
std::invoke(memFuncPtr, aPtr);
person 眠りネロク    schedule 21.08.2020
comment
Дальнейшее чтение для получения дополнительных приемов и инструментов при работе с необработанным указателем на функцию: Указатели на функции-члены< /а> - person user4581301; 21.08.2020
comment
@ user4581301 Спасибо за ссылку. Я расширил ответ для представления std::invoke. - person 眠りネロク; 26.08.2020