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

C++ 虚拟成员函数和std::tr1::function:这是如何工作的?,c++,inheritance,tr1,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;

下面是一段示例代码。请注意,
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;
}

我会考虑这个正确的行为,但是如果<>代码STD::Tr1::函数< /代码> s被绑定到<代码>:A::打印< /代码>这两种情况下,我都无法解释它是如何工作的。有人能告诉我吗

编辑:谢谢您的回答。我熟悉继承和多态类型。我感兴趣的是
&A::print
是什么意思?它是vtable的一个偏移量,并且vtable根据引用的对象(在本例中为
a
b
?)而变化。从更具体的角度来看,该代码如何正确地运行?

因为
print()
声明为
virtual
a
是一个多态类。通过绑定到
print
函数指针,您将通过
A
指针进行调用,调用方式与:

A* ab = &b;
ab->print();

在上面的
->print
调用中,您将看到多态行为。在代码中也是如此。如果你问我,这是件好事。至少,大多数时候是这样。:)

这与普通成员函数指针的工作方式相同。以下操作产生相同的输出:

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

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

如果使用Tr1,它应该被标记为C++。0x@John这个代码是在GCC 4.2下编译的C++,不接触C++ 0x。请你澄清一下你的立场好吗?@fbrereto:
tr1
名称空间中的所有内容都来自C++0x标准草案中的标准库提案;特别是技术报告1中的内容@fbereto:如果您使用的是TR1工具,那么根据定义,您使用的是C++0x。Tr1是C++0x@John:否,TR1不是C++0x。TR1是2005年提出的一套图书馆。C++0x是该标准的新修订版,有望于2011年发布。Rt1库不是C++标准库的一部分,这就是为什么它们都在 STD::Tr1命名空间中,而不是<代码> STD< /Cord>命名空间。TR1库已包含在C++0x标准库中(为此,它们已被移动到
std
命名空间)。您不仅绑定到print(),后者的行为与此处所述的多态性相同,还绑定到要从中调用它的对象。对象的类型因为第二个绑定而起作用。当我看到这个问题时,我想到的第一件事就是那篇文章!非常有趣和彻底。
int main ()
{
    A a;
    B b;
    typedef void (A::*fp)();
    fp p = &A::print;
    (a.*p)(); // prints A
    (b.*p)(); // prints B
}