Лучший и безопасный способ передать в функции extern в качестве параметра функцию класса без наддува? - PullRequest
1 голос
/ 06 марта 2012

У меня есть следующий код:

#include <iostream>

typedef void ( *FuncPtr )( int );

extern void MyFunc( FuncPtr callback )    

class MyClass
{
public:
    void SomeFunction( int n )
    {
        std::cout << "bla: " << n << std::endl;
    }
};

int main()
{
    MyClass obj;
    MyFunc( /*  */ );
}

Каков наилучший и безопасный способ передачи функции MyFunc в качестве параметра функции класса без (SomeFunction) повышения?

Ответы [ 2 ]

2 голосов
/ 06 марта 2012

Идиома для обратных вызовов C состоит в том, чтобы включать пользовательские данные , которые передают произвольный параметр через функцию и обратно в обратный вызов:

typedef void ( *FuncPtr )( int, uintptr_t user_data );

extern void MyFunc( FuncPtr callback, uintptr_t user_data );

При вызове метода в классе собратный вызов, который вы используете user_data для передачи указателя this:

class MyClass
{
public:
    void SomeFunction( int n )
    {
        std::cout << "bla: " << n << std::endl;
    }
private:
    static void SomeFunctionEntry( int n, uintptr_t user_data)
    {
        MyClass *ths = (MyClass *) user_data;
        ths->SomeFunction(n);
    }
};

Статическая функция SomeFunctionEntry является свободной функцией, которая может быть вызвана в качестве обратного вызова.Вы гарантируете, что его аргумент user_data является допустимым экземпляром класса:

int main()
{
    MyClass obj;
    MyFunc(&MyClass::SomeFunctionEntry, (uintptr_t) &obj);
}

(примечание: это очень плохая идея для передачи автоматической переменной, такой как obj, в качестве обратного вызовав многопоточной среде, потому что трудно быть уверенным, что указатель все еще будет действителен, когда обратный вызов в конечном счете вызывается)

2 голосов
/ 06 марта 2012

Вы не можете, и даже если ваш компилятор позволяет это, я уверен, что вы попали бы в неопределенное поведение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...