Предаване на указател към членска функция

Има редица примери, но все още не мога да разбера решението на моя проблем. аз имам

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;
};

След това, както казва ecatmur, можете да посочите статична функция-член за обратното извикване, но можете също да направите обикновена функция-член, която се извиква след думите:

Статичните членски функции нямат достъп до членовете на класа, но могат да бъдат посочени като обратни извиквания, където обикновено се изисква нормална 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