18

このような構造体がある場合

struct A {
    void func();
};

そして、このような参照

A& a;

func次のように、そのメソッドへのポインターを取得できます。

someMethod(&A::func);

そのメソッドが仮想で、実行時にそれが何であるかわからない場合はどうなるでしょうか? なぜこのようなポインターを取得できないのですか?

someMethod(&a.func);

そのメソッドへのポインターを取得することは可能ですか?

4

3 に答える 3

30

メンバーへのポインターは、それらが指す関数の仮想性を考慮に入れます。例えば:

#include <iostream>
struct Base
{
    virtual void f() { std::cout << "Base::f()" << std::endl; }
};

struct Derived:Base
{
    virtual void f() { std::cout << "Derived::f()" << std::endl; }
};


void SomeMethod(Base& object, void (Base::*ptr)())
{
    (object.*ptr)();    
}


int main()
{
    Base b;
    Derived d;
    Base* p = &b;
    SomeMethod(*p, &Base::f); //calls Base::f()
    p = &d;
    SomeMethod(*p, &Base::f); //calls Derived::f()    
}

出力:

Base::f()
Derived::f()
于 2011-07-19T22:22:43.667 に答える
11

関数ポインタを呼び出す方法は、そのオブジェクトのインスタンス ポインタも提供することです。これにより、すべての仮想性の問題が処理されます。

struct A { void func(); };

int main()
{
  typedef void (A::*mf)();

  A x; // irrelevant if A is derived or if func is virtual

  mf f = &A::func;   // pointer-to-member-function
  A* p = &x;         // pointer-to-instance

  (p->*f)();           // invoke via pointer
  (x.*f)();            // invoke directly
}

OK、興味深い構文チャレンジの質問: これがあるとします。

struct Basil { virtual void foo(); virtual ~Basil(); };
struct Derrek : public Basil { virtual void foo(); };

Derrek * pまたは がある場合、 を介してメンバーをBasil * p呼び出すことができます。が与えられた場合、どうすれば同じことができますか?Basilp->Basil::foo()void(Derrek::*q)() = &Derrek::foo

回答:できません。PMFqだけでは、それが仮想関数を指しているかどうか、ましてやどの仮想関数を指しているかがわからず、実行時に基本クラス関数を検索するために使用することはできません。[スティーブとリュックに感謝!]

于 2011-07-19T22:21:25.100 に答える
1

次のように、それへのポインタを取得できます。

struct A {
    virtual void foo() = 0;
};

typedef void (A::*LPFOO)();

LPFOO pFoo = &A::foo;
于 2011-07-19T22:23:04.847 に答える