Снова и снова ... Указатель на функцию-член - PullRequest
0 голосов
/ 12 января 2011

Предположим:

class Parser
{
  public:
  void parser1(int a, int b, int c);
  void parser2(int d, int e, int f);
  void setupPtr();

  void (Parser::*ptrParser) (int param1, int param2, int param3);
}

Parser::setupPtr()
{
   if(bla bla)
   {
       ptrParser = &Parser::parser1;
   }
   else
   {
       ptrParser = &Parser::parser2;
   }
}

в основном:

int main(argv, argc)
{
   Parser parser;
   parser.setupPtr();
// first case
   parser.ptrParser(some paramps); // error!    error C2064: term does not evaluate to a function taking 3 arguments
// second case
   parser.*ptrParser(some paramps); // error!   'ptrParser' : undeclared identifier
// third case
   (parser.*ptrParser)(some paramps); // error!     'ptrParser' : undeclared identifier


}

Ответы [ 4 ]

3 голосов
/ 12 января 2011

Учитывая, что вы изменили поле ptrParser на общедоступное, вам нужно написать main следующим образом:

int main()
{
   Parser parser;
   parser.setupPtr();
   (parser .* (parser.ptrParser))(1, 2, 3);
   return 0;
}

Давайте попробуем разобраться в строке.

Во-первых, для вызова функции указателя на член типа void (Parser::*)(int, int, int), учитывая экземпляр Parser с именем inst и функцию указателя на член func, синтаксис:

(inst .* func)(x, y, z);

В нашем случае экземпляр называется parser, а указатель на функцию-член сохраняется в поле ptrParser класса parser, доступ к которому осуществляется с помощью синтаксиса parser.ptrParser. Заменив его в предыдущем выражении, это дает нам (добавление скобок, потому что я не уверен в приоритетности операторов):

(parser .* (parser.ptrParser))(x, y, z);

Если вместо ссылки или объекта у нас есть указатель на Parser, синтаксис будет:

int main()
{
   Parser *parser = createAndInitializeParser();
   (parser ->* (parser->ptrParser))(1, 2, 3);
   markParserAsNotUsedDestroyIfNeeded(parser);
   return 0;
}
1 голос
/ 12 января 2011

Отличное введение / учебное пособие по указателям на функции (почти) всех форм и размеров: http://www.newty.de/fpt/index.html

Я полагаю, вы ищете часть 3.5.

0 голосов
/ 12 января 2011

Могу ли я предложить вам сделать typedef для вашей функции ptr type:

typedef void (Parser::*funcptr) (int , int , int );

, а затем создайте свой contener:

class Parser
{
public:
typedef void (Parser::*funcptr) (int , int , int );

void parser1(int a, int b, int c);
void parser2(int d, int e, int f);
void setupPtr();

funcptr firstptr;
}

для его установки:

firstptr = &Parser::parser1;

чтобы назвать это:

Parser foo;
foo.setupPtr;
(foo.*(foo.firstptr))(1, 2, 3);

Это менее сложно понять, и вы сможете создать массив funcptr ...

0 голосов
/ 12 января 2011

Я вижу две проблемы с этим кодом.

1) ptrParser не назначен ни для чего.Сначала необходимо вызвать Parser :: setupPtr.

2) ptrParser - это указатель на метод, который не принимает параметров, иными словами, вы должны определить его как содержащий параметры.Я думаю, что вы все еще можете обойтись без него, если перед тем, как вызывать его, произнесите его, но лучше оставить все просто.

Декларация для указателя метода для вашего конкретного примера будет выглядеть так:

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