2009-12-18 2 views
10

Я получаю ошибку компиляции (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. Что мне здесь не хватает?

+0

Синтаксис C является ржавым, поэтому не добавляя в качестве ответа, если он не будет «return (* (p-> pfn)) (val);»? - –

+0

Нет, это приводит к ошибке «* незаконна в операндах типа C :: PFN». – chrisd

+0

Возможный дубликат [Вызов методов класса C++ с помощью указателя функции] (http://stackoverflow.com/questions/1485983/calling-c-class-methods-via-a-function-pointer) –

ответ

17

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

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

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

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

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

Спасибо. Теперь я не только исправляю, я понимаю, почему. – chrisd

8

Попробуйте

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

ДА !! Вот и все. Спасибо. Вы, ребята, невероятны. Я накрутил это часами и получил ответ менее чем за 10 минут. – chrisd

-1

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

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

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

+9

«Откуда эта царапина на моем велосипеде?» - «Сделайте себе одолжение - купите самолет» –

0

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

1

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

(this -> *stateHandler)() ; 

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

(this->*stateHandler)() ; 

Я использую г ++ (GCC) 4.4.2 20090825 (пререлиз). FWIW.

Смежные вопросы