I stumbled upon a curiosity, when investigating the possibility of passing member functions as callbacks using boost::bind and boost::function. I was fooling around with a model of two classes. The first one (Organism) exposes its member variable (age) through an int(void) function (getAge). The second class (Biologist) stores a boost::function as a member (callbackFunction) and uses it to determine (takeNotes) the current age of the animal it is studying (it retains the age in the member variable m_notes). An instance (steve_irwin) of the second class is supposed to 'watch' (takeNotes) the instance (animal) of the first class.
Here is the code implementing the Animal class:
class Organism {
public:
Organism(int = 1);
void growOlder();
int getAge(void);
void tellAge(void);
private:
int m_age;
};
Organism::Organism(int _age) : m_age(_age) {}
void Organism::growOlder() {
m_age++;
}
int Organism::getAge(void) {
return m_age;
}
void Organism::tellAge(void) {
std::cout << "This animal is : " << m_age << " years old!";
}
Whereas this is the code implementing the Biologist class:
class Biologist {
public:
void setCallback(boost::function<int(void)>);
void takeNotes();
void tellAge();
private:
boost::function<int(void)> updateCallback;
int m_notes;
};
void Biologist::setCallback(boost::function<int(void)> _f) {
updateCallback = _f;
}
void Biologist::takeNotes() {
m_notes = updateCallback();
}
void Biologist::tellAge() {
std::cout << "The animal I am studying is : " << m_notes <<
" years old! WOW!" << std::endl;
}
The main loop goes like this:
Organism animal(3);
Biologist steve_irwin;
boost::function<int(void)> f = boost::bind(&Organism::getAge, animal);
steve_irwin.setCallback(f);
steve_irwin.takeNotes();
steve_irwin.tellAge();
animal.tellAge();
animal.growOlder();
steve_irwin.takeNotes();
steve_irwin.tellAge();
animal.tellAge();
I create an animal which is 3 years old, I tell Steve Irwin to watch it, he tells its age correctly after taking notes at first, but after the animal grows older and he tells its age again, he still thinks the animal is 3 years old.
The output of the program :
The animal I am studying is : 3 years old! WOW!
This animal is : 3 years old!
The animal I am studying is : 3 years old! WOW!
This animal is : 4 years old!
I am guessing I somehow failed to pass the member function as a callback by reference but I can't determine where. Can you help me?
Instead of boost::function<int(void)> f = boost::bind(&Organism::getAge, animal);
it should be boost::function<int(void)> f = boost::bind(&Organism::getAge, &animal);
, because boost::bind creates an internal copy of your object if you do as above.