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

Есть несколько примеров, но я все же не могу найти решение своей проблемы. у меня есть

class FooSource{
    ...

    void StartGetFoos(void (*callback)(vector<IFoo*>*, IAsyncResult));
    ...
}

Когда вызывается StartGetFoos(), выполняется запрос на получение Foos с сохранением обратного вызова. когда запрос завершается (занимает около 30 секунд), вызывается сохраненный обратный вызов с результатами. Я не могу изменить подпись этого метода.

и где-то еще у меня есть класс

class FooUser {
    ...

    void FooUser::MyCallback(vector<IFoo*>* foos, IAsyncResult result) 
    {
          // marshall to UI thread and update UI
    }

    void init()
    {
         fooUser->StartGetFoos(??????);
         // how do I pass my callback member function here?
    }
}

person Professor Chaos    schedule 25.06.2012    source источник
comment
связанные: stackoverflow.com/questions/1738313/   -  person Nate Kohl    schedule 26.06.2012


Ответы (2)


В подписи void (*callback)(vector<IFoo*>*, IAsyncResult) нет места для получения указателя this, поэтому вы не можете использовать функцию-член. Вместо этого вам придется использовать функцию-член static:

class FooUser {
    static void MyCallback(vector<IFoo*>* foos, IAsyncResult result) 
    {
          // marshall to UI thread and update UI
    }

    void init()
    {
         fooUser->StartGetFoos(&FooUser::MyCallback);
    }
};

Проблема здесь в том, что вы не сможете получить доступ к данным экземпляра на FooUser; это может быть, а может и не быть проблемой.

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

person ecatmur    schedule 25.06.2012
comment
Не могли бы вы подробнее рассказать о том, как использовать статическую функцию-член в этом случае? Я просматривал этот пост раньше и выглядело многообещающе, но я не мог ничего изменить в своей ситуации. Спасибо за помощь. - person Professor Chaos; 26.06.2012
comment
@ProfessorChaos, используйте статическую функцию-член для вызова другой нестатической функции-члена. Для этого статической функции необходимо откуда-то получить указатель на объект, возможно, статическую переменную-указатель-член, если у вас никогда не выполняется более одного обратного вызова. - person Mark Ransom; 26.06.2012

Если IAsyncResult - это структура данных, которая передается, а затем снова возвращается для операции, вы можете расширить ее своей собственной информацией.

class MyAsyncResult : public IAsyncResult
{
public:
   MyAsyncResult(FoorUser *sender) : sender(sender){}
   FooUser *sender;
};

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

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

class FooUser
{
    // static with no access to class members, but can be specified as a callback.
    static void MyCallback(vector<IFoo*>* foos, IAsyncResult *result) 
    {
          MyAsyncResult *res = (MyAsyncResult*)result;
          res->sender->MyCallback(foos, result);
    }

    void MyCallback(vector<IFoo*>* foos, IAsyncResult *result) 
    {
          // handle the actual callback here
    }

    void init()
    {
         IAsyncResult *res = new MyAsyncResult(this);
         fooUser->StartGetFoos(&foos, res);
    }
}
person CuriousGeorge    schedule 25.06.2012