Можно ли получить указатель на определение чистой виртуальной функции?

Возможный дубликат:
Вызов определения базового класса виртуальной функции-члена с указателем функции

Учитывая следующую иерархию:

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();

or:

Base * b = &d;

b->Base::f();

Никаких сюрпризов. Но возможно ли получить указатель на функцию-член, через которую можно вызвать Base::f?

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

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

(Для протокола: на самом деле мне это не нужно. Мне просто любопытно.)


person Andrew Durward    schedule 27.04.2012    source источник


Ответы (1)


Как прокомментировал Джеймс Макнеллис, короткий ответ - просто «нет».

Более длинный ответ: «если вы готовы принять формальный 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
}

Я бы не стал этого делать, но тогда я бы вообще не использовал необработанные указатели на функции-члены (связанные - другое дело, например, для событий графического интерфейса).

Обратите внимание, что если вы управляете классом Base, вы можете просто исключить функции, которые вы хотите сделать доступными без переопределения.

person Cheers and hth. - Alf    schedule 27.04.2012
comment
+1 за предоставление нового материала для моих кошмаров. - person Andrew Durward; 28.04.2012