开发者

C++ Pointer to virtual function

If you have a struct like this one

struct A {
    void func();
};

and a reference like this one

A& a;

you can 开发者_如何学Cget a pointer to its func method like this:

someMethod(&A::func);

Now what if that method is virtual and you don't know what it is at run-time? Why can't you get a pointer like this?

someMethod(&a.func);

Is it possible to get a pointer to that method?


Pointers to members take into account the virtuality of the functions they point at. For example:

#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()    
}

Outputs:

Base::f()
Derived::f()


The way to invoke a function pointer is to also provide its object's instance pointer. This will take care of all virtuality issues:

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, interesting syntax challenge question: Suppose I have this.

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

Now if I have Derrek * p or a Basil * p, I can invoke the Basil member via p->Basil::foo(). How could I do the same if I was given a void(Derrek::*q)() = &Derrek::foo?

Answer: It cannot be done. The PMF q alone does not know whether it points to a virtual function, let alone which one, and it cannot be used to look up a base class function at runtime. [Thanks to Steve and Luc!]


You can get a pointer to it, like so:

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

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

LPFOO pFoo = &A::foo;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜