Virtual member functions and std::tr1::function: How does this work?
Here is a sample piece of code. Note that B
is a subclass of A
and both provide a unique p开发者_如何学JAVArint
routine. Also notice in main
that both bind
calls are to &A::print
, though in the latter case a reference to B
is passed.
#include <iostream>
#include <tr1/functional>
struct A
{
virtual void print()
{
std::cerr << "A" << std::endl;
}
};
struct B : public A
{
virtual void print()
{
std::cerr << "B" << std::endl;
}
};
int main (int argc, char * const argv[])
{
typedef std::tr1::function<void ()> proc_t;
A a;
B b;
proc_t a_print = std::tr1::bind(&A::print, std::tr1::ref(a));
proc_t b_print = std::tr1::bind(&A::print, std::tr1::ref(b));
a_print();
b_print();
return 0;
}
Here is the output I see compiling with GCC 4.2:
A
B
I would consider this correct behavior, but I am at a loss to explain how it is working properly given that the std::tr1::function
s were bound to &A::print
in both cases. Can someone please enlighten me?
EDIT: Thanks for the answers. I am familiar with inheritance and polymorphic types. What I am interested in is what does &A::print
mean? Is it an offset into a vtable, and that vtable changes based on the referred object (in this case, a
or b
?) From a more nuts-and-bolts perspective, how does this code behave correctly?
This works in the same manner as it would have worked with plain member function pointers. The following produces the same output:
int main ()
{
A a;
B b;
typedef void (A::*fp)();
fp p = &A::print;
(a.*p)(); // prints A
(b.*p)(); // prints B
}
It would have been surprising if boost/tr1/std::function did anything different since they presumably store these pointers to member functions under the hood. Oh, and of course no mention of these pointers is complete without a link to the Fast Delegates article.
Because print()
is declared virtual
, A
is a polymorphic class. By binding to the print
function pointer, you will be calling through an A
pointer, much in the same way as:
A* ab = &b;
ab->print();
In the ->print
call above, you would expect polymorphic behavior. Same it true in your code as well. And this is a Good Thing, if you ask me. At least, most of the time. :)
精彩评论