I have a base class, a derived class, and a virtual member function. I also have a function which takes a base class reference and makes a polymorphic call to the member function:
#include <iostream>
#include <functional>
class Base
{
public:
Base() {}
virtual int getnum() { return 1; }
};
class Derived : public Base
{
public:
Derived() {}
virtual int getnum() { return 2; }
};
int getnumref(Base& b) { return b.getnum(); }
int main()
{
Derived d;
Base& bref = d;
std::cout << getnumref(bref) << std::endl;
}
Here, late binding occurs, and the output is 2
.
But if I now add the following lines to the main()
function in order to pre-define the argument to the function, and then call it:
std::function<int()> boundgetnumref = std::bind(getnumref, bref);
std::cout << boundgetnumref() << std::endl;
then the output of the last line is 1
, i.e. here, early binding occurs, and the member function of the base class is called.
If I use pointers, i.e.
//...
int getnumptr(Base* b) { return b->getnum(); }
//...
int main()
{
Derived d;
Base* bptr = &d;
std::cout << getnumptr(bptr) << std::endl;
std::function<int()> boundgetnumptr = std::bind(getnumptr, bptr);
std::cout << boundgetnumptr() << std::endl;
}
then the output of both cout
calls is 2
.
Why does early binding take place when I use pass-by-reference together with std::bind
, and not otherwise?
std::bind
stores captured arguments by value causing a slicing copy of Derived
to Base
.
If you just pass std::reference_wrapper
(a pointer) that would copy the pointer, so that slicing copy does not happen:
std::function<int()> boundgetnumref = std::bind(getnumref, std::ref(bref));
Prefer lambdas though, they are the best practice: easier to write, read and more efficient:
auto boundgetnumref = [&bref]() { return getnumref(breg); }