Как реализовать обратные вызовы, которые являются виртуальными функциями? - PullRequest
1 голос
/ 23 февраля 2012

Я использую wxWigets, но я полагаю, что этот вопрос больше о том, как реализовать обратные вызовы, которые являются виртуальными функциями.Это (очень) упрощенная версия моего кода:

// MyGUI.h 
Class MyGUI : public wxFrame {

  ...
  protected:
     virtual void onFeedButton_cb( wxCommandEvent& event ) { event.Skip(); }
  ...
}

// Animal.h 
Class Animal {

  public: 
       void Feed(); 
}

Тривиальный вопрос: как мне реализовать обратный вызов onFeedButton_cb, чтобы он мог получить доступ к функции Animal Feed () ??т.е. во время выполнения обратный вызов должен иметь доступ к экземпляру Animal.

Ответы [ 3 ]

5 голосов
/ 23 февраля 2012

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

#include <memory>
#include <iostream>

class Animal { virtual void Roar() { std::cout << "Roar!\n"; } };
class Rabbit : public class Animal { virtual void Roar() {
    std::cout << "Rabbits don't roar, silly!\n"; } };

typedef void (*NonVirtualCallbackType)(Animal *);

void Callback(Animal *foo)
{
    //Virtual call happens inside the callback
    foo->Roar();
}

void FunctionUsingCallback(NonVirtualCallbackType callback, Animal *instance)
{
    callback(instance);
}

int main()
{
    std::unique_ptr<Animal> generals(new Animal());
    std::unique_ptr<Animal> wabbits(new Rabbit());
    FunctionUsingCallback(Callback, generals);
    FunctionUsingCallback(Callback, wabbits);
}

Обратите внимание, что этот вид преобразования - это именно то, что делает std::mem_funпод прикрытиями для функторов STL, хотя это зависит от времени компиляции, а не от полиморфизма времени выполнения.

0 голосов
/ 26 февраля 2012

Что сработало для меня, так это:

class MyGUIChild : public MyGUI {
    Animal* animal_ptr; 

    void onFeedButton_cb( wxCommandEvent& event ) { 
        animal_ptr->feed(); 
    }
 }
0 голосов
/ 23 февраля 2012

Учитывая объяснения в ваших комментариях, кажется, вам нужно:

  • сделать код в MyGUI.h осведомленным о Animal

  • определяет глобальное хранилище для указателя на единственный Animal экземпляр

Возможно, что-то вроде этого:

// MyGUI.h 
#include "Animal.h"

Class MyGUI : public wxFrame {

  ...
  protected:
     virtual void onFeedButton_cb( wxCommandEvent& event ) {
        Animal::getTheAnimal()->Feed();
        event.Skip(); }
  ...
}

// Animal.h 
Class Animal {
  private:
       static Animal* theAnimal;

  public:
       static Animal& getTheAnimal() { return *theAnimal; }

  public:
       Animal() { theAnimal = this; }

  public: 
       void Feed(); 
}

См. Также шаблон Singleton .

...