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

时间:2010-09-09 17:13:29

标签: c++ inheritance tr1

这是一段代码示例。请注意,BA的子类,并且都提供唯一的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; } 的引用。

A
B

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

std::tr1::function

我会考虑这种正确的行为,但鉴于在这两种情况下&A::print都绑定到&A::print,我无法解释它是如何正常工作的。有人可以赐教我吗?

编辑:感谢您的回答。我熟悉继承和多态类型。我感兴趣的是a 是什么意思?它是vtable的偏移量,并且vtable基于引用的对象(在这种情况下,b或{{1}}进行更改?)从更加严格的角度来看,此代码的行为如何?正确?

2 个答案:

答案 0 :(得分:5)

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

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做了任何不同的事情,那将是令人惊讶的,因为他们可能会将这些指针存储在引擎盖下的成员函数中。哦,当然,如果没有指向the Fast Delegates article的链接,就不会提及这些指针。

答案 1 :(得分:2)

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

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

在上面的->print调用中,您会发现多态行为。在您的代码中也是如此。如果你问我,这是一件好事。至少,大部分时间。 :)