Как вызвать функцию-указатель-член?

Я получаю ошибку компиляции (MS VS 2008), которую я просто не понимаю. После долгих разговора с ним все расплывчато, и я чувствую, что там что-то очень очевидное (и очень глупо), которого я пропускаю. Вот основной код:

typedef int (C::*PFN)(int);

struct MAP_ENTRY
    {
    int id;
    PFN pfn;
    };

class C
    {
    ...
    int Dispatch(int, int);
    MAP_ENTRY *pMap;
    ...
    };

int C::Dispatch(int id, int val)
    {
    for (MAP_ENTRY *p = pMap; p->id != 0; ++p)
        {
        if (p->id == id)
            return p->pfn(val);  // <--- error here
        }
    return 0;
    }

Компилятор утверждает со стрелкой, что "термин не оценивает функцию, принимающую 1 аргумент". Почему нет? PFN прототипируется как функция с одним аргументом, а MAP_ENTRY.pfn является PFN. Что мне здесь не хватает?

Ответ 1

p->pfn - это указатель типа указателя на член. Чтобы вызвать функцию через такой указатель, вам нужно использовать оператор ->* или operator .* и поставить объект типа C в качестве левого операнда. Вы этого не сделали.

Я не знаю, какой объект типа C предполагается использовать здесь - только вы это знаете, но в вашем примере это может быть *this. В этом случае вызов может выглядеть следующим образом

(this->*p->pfn)(val)

Чтобы сделать его немного менее запутанным, вы можете ввести промежуточную переменную

PFN pfn = p->pfn;
(this->*pfn)(val);

Ответ 2

Try

return (this->*p->pfn)(val);

Ответ 3

Просто, чтобы прослушивать свой собственный опыт, я столкнулся с ошибкой в ​​g++, вызванной этим утверждением:

  (this -> *stateHandler)() ;

Где stateHandler является указателем на функцию элемента void класса, на который ссылается * this. Проблема была вызвана пробелами между оператором стрелки. Следующий фрагмент компиляции отлично:

(this->*stateHandler)() ;

Я использую g++ (GCC) 4.4.2 20090825 (preerelease). FWIW.

Ответ 4

Сделайте себе одолжение и используйте boost:: function (и boost:: bind too!)

Ответ 5

это не отвечает на ваш вопрос, но подумайте об использовании boost:: function и boost:: bind. Он вводит довольно большую зависимость в вашу кодовую базу, но это стоит того, чтобы делать крупные проекты.

Ответ 6

p- > pfn - указатель на функцию. Вы должны использовать *, чтобы сделать его функцией. Изменить на

(*(p->pfn))(val)