30

C ++では、クラスの(非静的)メンバー関数へのポインターを取得し、後でそれをオブジェクトで呼び出すことができます。関数が仮想の場合、呼び出しはオブジェクトの動的タイプに応じて動的にディスパッチされます。使用するバージョンを含むスコープを明示的に指定することにより、(メンバーポインターを使用せずに)オブジェクトの仮想メンバー関数を単相的に呼び出すこともできます。次のコードはこれを示しています。

#include <iostream>
using std::cout; using std::endl;

struct Foo
{
    virtual void foo() { cout << 1 << endl; }
};

struct Foo2: public Foo
{
    virtual void foo() { cout << 2 << endl; }
};

int main( int, char** )
{
    Foo *foo = new Foo2;

    void (Foo::*foo_pointer)() = &Foo::foo;

    foo->foo();            // prints 2
    foo->Foo::foo();       // prints 1
    (foo->*foo_pointer)(); // prints 2
}

私がやりたいのは、2つを組み合わせて、メンバー関数の単相バージョンへのポインターを取得することです。つまり、Foo :: fooへのポインタが必要です。これは、常にfooの基本クラスバージョンを呼び出し、Foo2で呼び出された場合でも1を出力します。しかし、私はこれを行う方法を見つけることができませんでした。出来ますか?

(単相呼び出しを行う新しい非仮想関数を手動で記述し、それへのポインターを取得するという面倒な手動の方法を除きます。)

4

3 に答える 3

12

それはGCCで可能ですが、C ++言語拡張セクションで文書化されている方法は、それを行うための移植可能な方法がないことを示唆しています。

あなたは2つのことをすることができます:

  1. クラスを制御する場合は、非仮想関数とその仮想ラッパーを作成し、仮想ディスパッチが必要ないことがわかっている場合は、非仮想ディスパッチのアドレスを取得します。
  2. そうでない場合は、メンバーポインターを保持し、明示的なスコープ呼び出しを行うテンプレートファンクターを作成します。
于 2011-02-21T15:46:15.247 に答える
0

言い換えれば、あなたはごまかしたいのです。

いいえ、それは、メンバーメソッドへのポインタと組み合わせたポリモーフィズムが機能する方法であるため、不可能です。

于 2011-02-21T10:27:53.617 に答える
0

多くの場合、これは実用的に好ましい解決策であるため、ラッパー関数のコード例を詳しく説明します(そして、OPがこのメソッドを避けたかったにもかかわらず!)。

#include <iostream>
using std::cout; using std::endl;

struct Foo
{
    virtual void foo() { cout << 1 << endl; }
};

struct Foo2: public Foo
{
    virtual void foo() { cout << 2 << endl; }
};

void monomorphicFooFoo( Foo * f ) { f->Foo::foo(); }

int main()
{
    Foo *foo = new Foo2;

    void (*baseFoo)( Foo * ) = &monomorphicFooFoo;
    baseFoo( foo ); // Prints 1
}
于 2015-04-21T08:41:19.203 に答える