C ++: указатель на мономорфную версию виртуальной функции-члена? - PullRequest
27 голосов
/ 21 февраля 2011

В C ++ возможно получить указатель на (нестатическую) функцию-член класса, а затем позднее вызвать ее для объекта.Если функция была виртуальной, вызов отправляется динамически в зависимости от динамического типа объекта.Также возможно (не используя указатель члена) вызывать виртуальные функции-члены объектов мономорфно, явно предоставляя область действия, содержащую версию для использования.Следующий код демонстрирует это:

#include <iostream>
using std::cout; using std::endl;

struct Foo
{
    virtual void foo() { cout << 1 << endl; }
};

struct Foo2: public Foo
{
    virtual void foo() { cout << 2 << endl; }
};

int main( int, char** )
{
    Foo *foo = new Foo2;

    void (Foo::*foo_pointer)() = &Foo::foo;

    foo->foo();            // prints 2
    foo->Foo::foo();       // prints 1
    (foo->*foo_pointer)(); // prints 2
}

Что я хотел бы сделать, это объединить два и получить указатель на мономорфную версию функции-члена;т.е. я хочу указатель на Foo :: foo, который всегда вызывает версию foo базового класса и печатает 1, даже если он вызывается на Foo2.Тем не менее, я не смог найти способ сделать это.Возможно ли это?

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

Ответы [ 3 ]

10 голосов
/ 21 февраля 2011

Это возможно в GCC , но способ, описанный в разделе расширений языка C ++, предполагает, что нет портативного способа сделать это.

Вы можете сделать две вещи:

  1. Если вы управляете классом, создаете не виртуальную функцию и виртуальную оболочку для него, и когда вы знаете, что вам не нужна виртуальная диспетчеризация, просто возьмите адрес не виртуальной.
  2. Если вы этого не сделаете, создайте шаблонный функтор, который будет содержать указатель на член и выполнять явный вызов области.
0 голосов
/ 21 апреля 2015

Разработать пример кода для функции-оболочки (и несмотря на то, что ОП хотел избежать этого метода!), Поскольку во многих случаях это прагматически предпочтительное решение:

#include <iostream>
using std::cout; using std::endl;

struct Foo
{
    virtual void foo() { cout << 1 << endl; }
};

struct Foo2: public Foo
{
    virtual void foo() { cout << 2 << endl; }
};

void monomorphicFooFoo( Foo * f ) { f->Foo::foo(); }

int main()
{
    Foo *foo = new Foo2;

    void (*baseFoo)( Foo * ) = &monomorphicFooFoo;
    baseFoo( foo ); // Prints 1
}
0 голосов
/ 21 февраля 2011

Другими словами: вы хотите обмануть.

Нет, это невозможно, потому что так работает полиморфизм в сочетании с указателем на метод-член.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...