2

重複の可能性:
関数ポインターを使用して仮想メンバー関数の基本クラス定義を呼び出す

次の階層があるとします。

struct Base
{
  virtual void f() = 0;
};

void Base::f()
{
  cout << "Base::f\n";
}

struct Derived : Base
{
  void f()
  {
    cout << "Derived::f\n";
  }
};

Base::f次のように呼び出しを強制できます。

Derived d;

d.Base::f();

また:

Base * b = &d;

b->Base::f();

そこに驚きはありません。しかし、呼び出すことができるメンバー関数ポインターを取得することは可能Base::fですか?

void (Base::*bf)() = &Base::f;

for_each( b, b+1, mem_fn( bf ) ); // calls Derived::f

(記録のために、私は実際にこれを行う必要はありません。私はただ興味があります。)

4

1 に答える 1

2

James McNellis がコメントしたように、短い答えは単に「いいえ」です。

より長い答えは、「正式なUBを受け入れる気があるなら」です。

#include <iostream>
#include <algorithm>    // for_each
#include <functional>      // mem_fn
using namespace std;

struct Base
{
  virtual void f() = 0;
};

void Base::f()
{
  cout << "Base::f\n";
}

struct Derived : Base
{
  void f()
  {
    cout << "Derived::f\n";
  }
};

int main()
{
    struct DirtyHack: Base
    {
        void baseF() { Base::f(); }
    };

    Derived d;
    void (Base::*bf)() = static_cast< void(Base::*)() >( &DirtyHack::baseF );
    Base* b = &d;

    (b->*bf)();
    for_each( b, b+1, mem_fn( bf ) ); // calls Base::f
}

私はこれをしませんが、一般的に生のメンバー関数ポインターは使用しません (バインドされたものは、GUI イベントなどでは別の問題です)。

クラスを制御する場合はBase、オーバーライドせずにアクセスできるようにする機能を除外できることに注意してください。

于 2012-04-27T19:59:40.063 に答える