glutReshapeFunc (метод класса) [дубликат]

Вот еще одна вариация в технике, подобная Bjorn's (apphacker), которая позволяет вам назначать значение переменной внутри функции, а не передавать ее как параметр, который иногда может быть более ясным:

for (var i = 0; i < 3; i++) {
    funcs[i] = (function() {
        var index = i;
        return function() {
            console.log("My value: " + index);
        }
    })();
}

Обратите внимание, что любой метод, который вы используете, переменная index становится своего рода статической переменной, связанной с возвращенной копией внутренней функции. I.e., изменения его значения сохраняются между вызовами. Это может быть очень удобно.

50
задан btlog 17 May 2016 в 20:21
поделиться

8 ответов

Как вы теперь показали, ваша функция init принимает не-членную функцию. так что сделайте это так:

static void Callback(int other_arg, void * this_pointer) {
    CLoggersInfra * self = static_cast<CLoggersInfra*>(this_pointer);
    self->RedundencyManagerCallBack(other_arg);
}

и вызовите Init с

m_cRedundencyManager->Init(&CLoggersInfra::Callback, this);

Это работает, потому что указатель функции на статическую функцию-член не является указателем на функцию-член и может таким образом обрабатываться как указатель на свободную функцию.

40
ответ дан Johannes Schaub - litb 27 August 2018 в 04:54
поделиться
91
ответ дан Community 27 August 2018 в 04:54
поделиться

Доступна ли функция m_cRedundencyManager для использования функций-членов? Большинство обратных вызовов настроены на использование регулярных функций или статических функций-членов.

Обновление: Объявление функции, которое вы указали, показывает, что m_cRedundencyManager ожидает, что функция вида: void yourCallbackFunction(int, void *). Поэтому функции-члены неприемлемы как обратные вызовы в этом случае. Статическая функция-член может работать, но если это неприемлемо в вашем случае, будет работать и следующий код. Обратите внимание, что он использует злое действие из void *.


// in your CLoggersInfra constructor:
m_cRedundencyManager->Init(myRedundencyManagerCallBackHandler, this);

// in your CLoggersInfra header:
void myRedundencyManagerCallBackHandler(int i, void * CLoggersInfraPtr);

// in your CLoggersInfra source file:
void myRedundencyManagerCallBackHandler(int i, void * CLoggersInfraPtr)
{
    ((CLoggersInfra *)CLoggersInfraPtr)->RedundencyManagerCallBack(i);
}
3
ответ дан e.James 27 August 2018 в 04:54
поделиться

Указатель на функцию-член класса не совпадает с указателем на функцию. Член класса принимает неявный дополнительный аргумент (указатель этого ), и использует другое соглашение о вызове.

Если ваш API ожидает функцию обратного вызова без ответа, это то, что вам нужно пройти к нему.

2
ответ дан jalf 27 August 2018 в 04:54
поделиться

Какой аргумент делает Init? Какое новое сообщение об ошибке?

Указатели метода на C ++ немного сложны в использовании. Помимо самого указателя метода, вам также необходимо указать указатель экземпляра (в вашем случае this). Может быть, Init ожидает, что это будет отдельный аргумент?

3
ответ дан Konrad Rudolph 27 August 2018 в 04:54
поделиться

Я вижу, что init имеет следующее переопределение:

Init (CALLBACK_FUNC_EX callback_func, void * callback_parm)

, где CALLBACK_FUNC_EX is typedef void (* CALLBACK_FUNC_EX) (int, void *); [/ д2]

1
ответ дан ofer 27 August 2018 в 04:54
поделиться

Этот вопрос и ответ из C ++ FAQ Lite охватывает ваш вопрос и соображения, связанные с ответом, довольно красиво, я думаю. Короткие фрагменты с веб-страницы, с которой я связан:

Do not.

Поскольку функция-член бессмысленна, если объект не вызывает его, вы не можете этого сделать (если система X Window была переписана на C ++, она, вероятно, передавала бы ссылки на объекты, а не только указатели на функции, естественно, объекты воплотили бы требуемую функцию и, вероятно, намного больше).

0
ответ дан Onorio Catenacci 27 August 2018 в 04:54
поделиться

Этот ответ является ответом на комментарий выше и не работает с VisualStudio 2008, но должен быть предпочтительнее с более поздними компиляторами.


Между тем вам больше не нужно использовать указатель void и нет необходимости в усилении, так как доступны std::bind и std::function . Преимущество одного (по сравнению с указателями void) - это безопасность типа, поскольку тип возврата и аргументы явно указаны с помощью std::function:

// std::function<return_type(list of argument_type(s))>
void Init(std::function<void(void)> f);

Затем вы можете создать функцию указатель с std::bind и передать его Init:

auto cLoggersInfraInstance = CLoggersInfra();
auto callback = std::bind(&CLoggersInfra::RedundencyManagerCallBack, cLoggersInfraInstance);
Init(callback);

Полный пример для использования std::bind с членами, статическими членами и не-членными функциями:

#include <functional>
#include <iostream>
#include <string>

class RedundencyManager // incl. Typo ;-)
{
public:
    // std::function<return_type(list of argument_type(s))>
    std::string Init(std::function<std::string(void)> f) 
    {
        return f();
    }
};

class CLoggersInfra
{
private:
    std::string member = "Hello from non static member callback!";

public:
    static std::string RedundencyManagerCallBack()
    {
        return "Hello from static member callback!";
    }

    std::string NonStaticRedundencyManagerCallBack()
    {
        return member;
    }
};

std::string NonMemberCallBack()
{
    return "Hello from non member function!";
}

int main()
{
    auto instance = RedundencyManager();

    auto callback1 = std::bind(&NonMemberCallBack);
    std::cout << instance.Init(callback1) << "\n";

    // Similar to non member function.
    auto callback2 = std::bind(&CLoggersInfra::RedundencyManagerCallBack);
    std::cout << instance.Init(callback2) << "\n";

    // Class instance is passed to std::bind as second argument.
    // (heed that I call the constructor of CLoggersInfra)
    auto callback3 = std::bind(&CLoggersInfra::NonStaticRedundencyManagerCallBack,
                               CLoggersInfra()); 
    std::cout << instance.Init(callback3) << "\n";
}

Возможный выход:

Hello from non member function!
Hello from static member callback!
Hello from non static member callback!

Кроме того, используя std::placeholders , вы можете динамически передавать аргументы для обратного вызова (например, это позволяет использовать return f("MyString"); в Init, если f имеет строковый параметр).

4
ответ дан Roi Danton 27 August 2018 в 04:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: