Вопрос в следующем: рассмотрите этот фрагмент кода:
#include <iostream>
class aClass
{
public:
void aTest(int a, int b)
{
printf("%d + %d = %d", a, b, a + b);
}
};
void function1(void (*function)(int, int))
{
function(1, 1);
}
void test(int a,int b)
{
printf("%d - %d = %d", a , b , a - b);
}
int main (int argc, const char* argv[])
{
aClass a();
function1(&test);
function1(&aClass::aTest); // <-- How should I point to a's aClass::test function?
return 0;
}
Как я могу использовать a
's aClass::test
в качестве аргумента function1
? Я застрял в этом.
Я хочу получить доступ к члену класса.
c++
arguments
parameter-passing
function-pointers
pointer-to-member
Хорхе Лейтао
источник
источник
Ответы:
Нет ничего плохого в использовании указателей на функции. Однако указатели на нестатические функции-члены не похожи на обычные указатели на функции: функции-члены должны вызываться для объекта, который передается в качестве неявного аргумента функции. Подпись вашей функции-члена выше, таким образом
а не тот тип, который вы пытаетесь использовать
Один из подходов может заключаться в создании функции-члена, и
static
в этом случае она не требует вызова какого-либо объекта, и вы можете использовать ее с типомvoid (*)(int, int)
.Если вам нужно получить доступ к любому нестатическому члену вашего класса, и вам нужно придерживаться указателей функций, например, поскольку функция является частью интерфейса C, ваш лучший вариант - всегда передавать a
void*
вашей функции, принимая указатели на функции и вызывать ваш член через функцию пересылки, которая получает объект из,void*
а затем вызывает функцию-член.В правильном интерфейсе C ++ вы можете захотеть посмотреть, как ваша функция принимает шаблонный аргумент для объектов функции, чтобы использовать произвольные типы классов. Если использование шаблонного интерфейса нежелательно, вы должны использовать что-то вроде
std::function<void(int, int)>
: вы можете создать соответствующий вызываемый объект функции для них, например, используяstd::bind()
.Типобезопасные подходы с использованием аргумента шаблона для типа класса или подходящего
std::function<...>
предпочтительнее, чем использованиеvoid*
интерфейса, поскольку они устраняют возможность ошибок из-за приведения к неправильному типу.Чтобы прояснить, как использовать указатель функции для вызова функции-члена, вот пример:
источник
void*
, а это означает, что вы можете получить очень неприятные ошибки, потому что он больше не проверяется типом.Ответ @Pete Becker в порядке, но вы также можете сделать это, не передавая
class
экземпляр в качестве явного параметраfunction1
в C ++ 11:источник
void function1(std::function<void(int, int)>)
правильно?void function1(std::function<void(int, int)> functionToCall)
а потомfunctionToCall(1,1);
. Я попытался отредактировать ответ, но кто-то отклонил его как бессмысленный по какой-то причине. Посмотрим, получит ли он когда-нибудь поддержку.Указатель на функцию-член отличается от указателя на функцию. Чтобы использовать функцию-член через указатель, вам нужен указатель на нее (очевидно) и объект, к которому его нужно применить. Таким образом, подходящей версией
function1
будети назвать это:
источник
function
вvoid (aClass::*function)(int, int)
был типа, из - за его типа вtypedef void (aClass::*function)(int, int)
.typedef int X;
определяет тип;int X;
создает объект.С 2011 года, если вы можете изменить
function1
, сделайте это, например:( живая демонстрация )
Также обратите внимание, что я исправил определение вашего сломанного объекта (
aClass a();
объявляет функцию).источник
Я задал аналогичный вопрос ( C ++ openframeworks передает void из других классов ), но ответ, который я нашел, был более ясным, поэтому вот объяснение для будущих записей:
проще использовать std :: function, как в:
а затем позвоните как:
или даже проще:
где вы создаете лямбду, которая вызывает объект, захватывающий его по ссылке
источник
std::function
indraw
вместо того, чтобы копировать ее при каждом вызове.Я сделал функцию-член статической, и все работает:
источник
Не уверен, почему это невероятно простое решение было пропущено:
Вывод:
источник
Если вы на самом деле не нужно использовать экземпляр
a
(т.е. вы можете сделать его статическим , как @mathengineer «s ответ ) вы можете просто передать без захвата лямбда. (которые распадаются на указатель функции)Wandbox
Примечание: если
aClass
строительство требует больших затрат или имеет побочный эффект, это может быть не лучшим способом.источник
Вы можете перестать биться головой. Вот оболочка для функции-члена для поддержки существующих функций, принимающих простые функции C в качестве аргументов.
thread_local
директива здесь является ключевой.http://cpp.sh/9jhk3
Прокомментируйте любые проблемы с этим подходом.
Другие ответы не вызывают существующие простые
C
функции: http://cpp.sh/8exunисточник
C
функции в качестве аргументов.