I wrote some code and got scared that it will not work - so I wrote a prototype:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
class base {
private:
boost::function<void (int)> action;
protected:
virtual void onDataBaseReady(int i) { std::cout << i << std::endl; }
public:
void call() {
action(10);
}
base() {
action = boost::bind(&base::onDataBaseReady, this, _1);
}
};
class child : public base {
protected:
virtual void onDataBaseReady(int i) { std::cout << i+10 << std::endl; }
};
int main()
{
static child c;
c.call();
std::cin.get();
return 0;
}
that compiles and works. (outputs 20
). But Why? Also I tested under VS2010 and wonder if it would work across platforms (say compiled under GCC)?
Mainly action = boost::bind(&base::onDataBaseReady, this, _1);
scares me - we say &base::
...
A pointer to a
virtual
method does avirtual
function lookup when called.so, it "just works". The member function pointer
(this->*&base::foo)()
is not the same as a fully qualified function callthis->base::foo()
. The first is a way to store thefoo
part of callingthis->foo()
, the second is a way to skipvirtual
method lookup and directly callbase::foo
.It would actually be much more scary if it performed static dispatch, rather than dynamic dispatch. Consider this simple example:
And then consider that you bind the function at the parent and call it on the derived object. The implementor of
derived
knows what invariants apply to the derived type, which might be the same, a subset or completely different than the invariants in the base type.If dispatch was resolved at binding time, and the functor was applied to the derived type (of which you might not know the exact type!) then the invariants of the derived type might be broken. In the context of the
apply
function it is impossible to know what the object really is, or what the invariants of that type are, so what you probably want to do is let dynamic dispatch do its magic.[That is from a high level design point of view, without even going into the detail that you cannot use a pointer to member to perform static dispatch...]