dr_rk
dr_rk

Reputation: 4565

How to implement callbacks that are virtual functions?

I am using wxWigets, but I suppose this question is more of how to implement callbacks that are virtual functions. This is a (very) simplified version of my code:

// MyGUI.h 
Class MyGUI : public wxFrame {

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

// Animal.h 
Class Animal {

  public: 
       void Feed(); 
}

A trivial question: How do I implement the onFeedButton_cb callback so that it can access Animal's Feed() function?? i.e. during run time the callback must have access to an instance of Animal.

Upvotes: 1

Views: 4195

Answers (3)

dr_rk
dr_rk

Reputation: 4565

What worked for me was this:

class MyGUIChild : public MyGUI {
    Animal* animal_ptr; 

    void onFeedButton_cb( wxCommandEvent& event ) { 
        animal_ptr->feed(); 
    }
 }

Upvotes: 0

krlmlr
krlmlr

Reputation: 25444

Given the explanations in your comments, it seems you need to:

  • make the code in MyGUI.h aware of Animal

  • define a global storage for a pointer to the only Animal instance

Perhaps something like this:

// 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(); 
}

See also the Singleton pattern.

Upvotes: 0

Billy ONeal
Billy ONeal

Reputation: 106530

Define a non-virtual function that calls the virtual function for you, and attach the non-virtual function to the callback.

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

Note that this kind of conversion is exactly what std::mem_fun does under the covers for STL functors, though it relies on compile time rather than runtime polymorphism.

Upvotes: 6

Related Questions