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

发布于 2024-09-18 14:58:00 字数 1181 浏览 5 评论 0原文

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

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

A
B

我会认为这是正确的行为,但我无法解释它如何正常工作,因为 std::tr1::function 是在这两种情况下都绑定到 &A::print 。有人可以启发我吗?

编辑:感谢您的回答。我熟悉继承和多态类型。我感兴趣的是 &A::print 是什么意思?它是 vtable 的偏移量,并且 vtable 根据引用的对象(在本例中为 ab?)而变化? ,这段代码如何正确运行?

Here is a sample piece of code. Note that B is a subclass of A and both provide a unique print 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::functions 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薄荷港 2024-09-25 14:58:00

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

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

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.

雪化雨蝶 2024-09-25 14:58:00

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

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

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

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. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文