Search code examples
c++boostboost-bindboost-function

Boost::Bind and virtual function overloads: why do they work?


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::...


Solution

  • A pointer to a virtual method does a virtual function lookup when called.

    #include <iostream>
    #include <memory>
    
    struct base {
      virtual void foo() { std::cout << "base\n"; }
      virtual ~base() {}
    };
    
    struct derived:base {
      void foo() override final { std::cout << "derived\n"; }
    };
    
    int main() {
      void (base::*mem_ptr)() = &base::foo;
      std::unique_ptr<base> d( new derived() );
      base* b = d.get();
      (b->*mem_ptr)();
    }
    

    so, it "just works". The member function pointer (this->*&base::foo)() is not the same as a fully qualified function call this->base::foo(). The first is a way to store the foo part of calling this->foo(), the second is a way to skip virtual method lookup and directly call base::foo.