С++ Указатель на виртуальную функцию
Если у вас есть такая структура, как эта
struct A {
void func();
};
и ссылка, подобная этой
A& a;
вы можете получить указатель на свой метод func
следующим образом:
someMethod(&A::func);
Теперь, что, если этот метод является виртуальным, и вы не знаете, что это такое во время выполнения? Почему вы не можете получить такой указатель?
someMethod(&a.func);
Можно ли получить указатель на этот метод?
Ответы
Ответ 1
Указатели членов учитывают виртуальность функций, на которые они указывают.
Например:
#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()
Ответ 2
Способ вызова указателя функции также должен содержать указатель на экземпляр объекта. Это позаботится обо всех проблемах с виртуальностью:
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
}
ОК, интересный запрос синтаксиса: предположим, что у меня есть это.
struct Basil { virtual void foo(); virtual ~Basil(); };
struct Derrek : public Basil { virtual void foo(); };
Теперь, если у меня есть Derrek * p
или Basil * p
, я могу вызвать член Basil
через p->Basil::foo()
. Как я мог сделать то же самое, если мне дали void(Derrek::*q)() = &Derrek::foo
?
Ответ: Это невозможно. Только PMF q
не знает, указывает ли он на виртуальную функцию, не говоря уже о которой, и не может быть использована для поиска функции базового класса во время выполнения. [Спасибо Стиву и Люку!]
Ответ 3
Вы можете получить указатель на него, например:
struct A {
virtual void foo() = 0;
};
typedef void (A::*LPFOO)();
LPFOO pFoo = &A::foo;