虚拟成员函数和std :: tr1 :: function:这是如何工作的?

fbr*_*eto 3 c++ inheritance tr1

这是一段代码示例.注意,它B是一个子类,A并且都提供了一个独特的print例程.另请注意main,两个bind调用都是&A::print,但在后一种情况下,B将传递引用.

#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;
}
Run Code Online (Sandbox Code Playgroud)

这是我看到用GCC 4.2编译的输出:

A
B
Run Code Online (Sandbox Code Playgroud)

我会考虑这种正确的行为,但我无法解释它是如何正常工作的,因为在两种情况下std::tr1::functions都必然&A::print存在.有人可以赐教吗?

编辑:谢谢你的答案.我熟悉继承和多态类型.我感兴趣的是什么&A::print 意思?它是vtable的偏移量,并且vtable基于引用的对象进行更改(在这种情况下,a或者b?)从更加坚定的角度来看,这段代码的行为是如何正确的?

Cub*_*bbi 5

这与使用普通成员函数指针的方式相同.以下产生相同的输出:

int main ()
{
    A a;
    B b;
    typedef void (A::*fp)();
    fp p = &A::print;
    (a.*p)(); // prints A
    (b.*p)(); // prints B
}
Run Code Online (Sandbox Code Playgroud)

如果boost/tr1/std :: function做了任何不同的事情,那将是令人惊讶的,因为他们可能会将这些指针存储在引擎盖下的成员函数中.哦,当然,如果没有Fast Delegates文章的链接,不会提及这些指针.