3

これがサンプルコードです。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;
}

GCC4.2でコンパイルした出力は次のとおりです。

A
B

私はこの正しい振る舞いを検討しますが、両方の場合std::tr1::functionにsがバインドされていることを考えると、それがどのように正しく機能しているかを説明するのに迷っています。&A::print誰かが私を教えてくれませんか?

編集:答えてくれてありがとう。私は継承とポリモーフィック型に精通しています。私が興味を持っているのはどういう&A::print 意味ですか?aそれはvtableへのオフセットであり、そのvtableは参照されるオブジェクト(この場合、または?)に基づいて変化します。より基本b的な観点から、このコードはどのように正しく動作しますか?

4

2 に答える 2

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が、メンバー関数へのこれらのポインターを内部で格納していると思われるため、何か別のことをしたとしたら、驚くべきことでした。ああ、そしてもちろん、これらのポインタについての言及は、FastDelegatesの記事へのリンクなしでは完全ではありません。

于 2010-09-09T17:41:42.620 に答える
2

print()が宣言されているためvirtualAはポリモーフィッククラスです。関数ポインタにバインドすることにより、次のように、ポインタprintを介して呼び出すことになります。A

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

上記の->print呼び出しでは、ポリモーフィックな動作が期待されます。あなたのコードでも同じです。そして、あなたが私に尋ねれば、これは良いことです。少なくとも、ほとんどの場合。:)

于 2010-09-09T17:20:57.513 に答える