2011-01-12 2 views
0

Предположим:Снова и снова ... Указатель на член-функции

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 


} 
+0

Вы понимаете, что все ваши члены в классе являются 'private', поэтому вы не можете получить к ним доступ из' main'? –

+0

Извините, отредактируйте код .. originaly its public – StNickolay

+0

Что вы действительно пытаетесь достичь? Очень возможно, что вам не нужны указатели на функции. –

ответ

3

Учитывая, что вы измените 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; 
} 
+0

ничего себе! Я в шоке, но это скомпилировано! Теперь мне нужно понять, что это значит). Благодаря! – StNickolay

+0

Я добавил несколько объяснений. Надеюсь, теперь это достаточно ясно. –

+0

это не тривиальный фрагмент, я этого раньше не видел) – StNickolay

1

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

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

+0

+1 для ссылки ^^ – neuro

0

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

1) ptrПарсер не привязан ни к чему. Сначала нужно вызвать Parser :: setupPtr.

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

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

void (Parser::*ptrParser) (int, int, int); 
+0

Царапины # 2. Вопрос изменен, чтобы включить параметры. – Neil

+0

извините за бит сломанный код, я написал их на лету и забыл параметры в определении func-ptr. Но вопрос все еще активен. – StNickolay

0

я хотел бы предложить вам сделать ЬурейеЕ вашей функции типа PTR:

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

, а затем создать свой Контенер:

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 ...

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