powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / как созжать указатель на функцию
25 сообщений из 53, страница 1 из 3
как созжать указатель на функцию
    #34181768
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
помогите, как мне создать указатель на функцию и передать его в качестве параметра другой ф-ции и там вызвать по этому указателю функцию ???
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181775
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Указатели на функции

Указатели на функции[1] — очень мощное средство языка С. Хотя нельзя не отметить, что это весьма трудный для понимания термин. Функция располагается в памяти по определенному адресу, который можно присвоить указателю в качестве его значения. Адресом функции является ее точка входа. Именно этот адрес используется при вызове функции. Так как указатель хранит адрес функции, то она может быть вызвана с помощью этого указателя. Он позволяет также передавать ее другим функциям в качестве аргумента.

В программе на С адресом функции служит ее имя без скобок и аргументов (это похоже на адрес массива, который равен имени массива без индексов). Рассмотрим следующую программу, в которой сравниваются две строки, введенные пользователем. Обратите внимание на объявление функции check() и указатель p внутри main(). Указатель p, как вы увидите, является указателем на функцию.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
#include <stdio.h>
#include <string.h>

void check(char *a, char *b,
           int (*cmp)(const char *, const char *));

int main(void)
{
  char s1[ 80 ], s2[ 80 ];
  int (*p)(const char *, const char *);
               /* указатель на функцию */

  p = strcmp;
  /* присваивает адрес функции strcmp указателю p */

  printf("Введите две строки.\n");
  gets(s1);
  gets(s2);

  check(s1, s2, p); /* Передает адрес функции strcmp
                       посредством указателя p */

  return  0 ;
}

void check(char *a, char *b,
           int (*cmp)(const char *, const char *))
{
  printf("Проверка на совпадение.\n");
  if(!(*cmp)(a, b)) printf("Равны");
  else printf("Не равны");
}

Проанализируем эту программу подробно. В первую очередь рассмотрим объявление указателя p в main():

Код: plaintext
int (*p)(const char *, const char *);

Это объявление сообщает компилятору, что p — это указатель на функцию, имеющую два параметра типа const char * и возвращающую значение типа int. Скобки вокруг p необходимы для правильной интерпретации объявления компилятором. Подобная форма объявления используется также для указателей на любые другие функции, нужно лишь внести изменения в зависимости от возвращаемого типа и параметров функции.

Теперь рассмотрим функцию check(). В ней объявлены три параметра: два указателя на символьный тип (a и b) и указатель на функцию cmp. Обратите внимание на то, что указатель функции cmp объявлен в том же формате, что и p. Поэтому в cmp можно хранить значение указателя на функцию, имеющую два параметра типа const char * и возвращающую значение int. Как и в объявлении p, круглые скобки вокруг *cmp необходимы для правильной интерпретации этого объявления компилятором.

Вначале в программе указателю p присваивается адрес стандартной библиотечной функции strcmp(), которая сравнивает строки. Потом программа просит пользователя ввести две строки и передает указатели на них функции check(), которая их сравнивает. Внутри check() выражение

(*cmp)(a, b)

вызывает функцию strcmp(), на которую указывает cmp, с аргументами a и b. Скобки вокруг *cmp обязательны. Существует и другой, более простой, способ вызова функции с помощью указателя:

cmp(a, b);

Однако первый способ используется чаще (и мы рекомендуем использовать именно его), потому что при втором способе вызова указатель cmp очень похож на имя функции, что может сбить с толку читающего программу. В то же время у первого способа записи есть свои преимущества, например, хорошо видно, что функция вызывается с помощью указателя на функцию, а не имени функции. Следует отметить, что первоначально в С был определен именно первый способ вызова.

Вызов функции check() можно записать, используя непосредственно имя strcmp():

Код: plaintext
check(s1, s2, strcmp);

В этом случае вводить в программу дополнительный указатель p нет необходимости.

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

Альтернативный подход — использование оператора switch с длинным списком меток case — делает программу более громоздкой и подверженной ошибкам.

В следующем примере рассматривается расширенная версия предыдущей программы. В этой версии функция check() устроена так, что может выполнять разные операции над строками s1 и s2 (например, сравнивать каждый символ с соответствующим символом другой строки или сравнивать числа, записанные в строках) в зависимости от того, какая функция указана в списке аргументов. Например, строки "0123" и "123" отличаются, однако представляют одно и то же числовое значение.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

void check(char *a, char *b,
           int (*cmp)(const char *, const char *));
int compvalues(const char *a, const char *b);

int main(void)
{
  char s1[ 80 ], s2[ 80 ];

  printf("Введите два значения или две строки.\n");
  gets(s1);
  gets(s2);

  if(isdigit(*s1)) {
    printf("Проверка значений на равенство.\n");
    check(s1, s2, compvalues);
  }
  else {
    printf("Проверка строк на равенство.\n");
    check(s1, s2, strcmp);
  }

  return  0 ;
}

void check(char *a, char *b,
           int (*cmp)(const char *, const char *))
{
  if(!(*cmp)(a, b)) printf("Равны");
  else printf("Не равны");
}

int compvalues(const char *a, const char *b)
{
  if(atoi(a)==atoi(b)) return  0 ;
  else return  1 ;
}
Если в этом примере ввести первый символ первой строки как цифру, то check() использует compvalues(), в противном случае — strcmp(). Функция check() вызывает ту функцию, имя которой указано в списке аргументов при вызове check(), поэтому она в разных ситуациях может вызывать разные функции. Ниже приведены результаты работы этой программы в двух случаях:

Введите два значения или две строки.
тест
тест
Проверка строк на равенство.
Равны

Введите два значения или две строки.
0123
123
Проверка значений на равенство.
Равны

Сравнение строк 0123[2] и 123 показывает равенство их значений.

----------

[1]Иногда их называют просто указателями функций. Но следует помнить, что в языках программирования под этим термином подразумевается также средство обращения к подпрограмме-функции или встроенной функции, имеющее конструкцию <имя-функции> (<список-аргументов>).

[2]Обратите внимание, что в языке С нулем начинаются восьмеричные константы. Если бы эта запись была в выражении, то 0123 не было бы равно 123. Однако здесь функция atoi() обрабатывает это число как десятичное.
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181802
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
при передаче в функцию выдает сл. ошибку
cannot convert parameter 1 from 'void (__thiscall ClinksDlg::* )(void)' to 'void (__cdecl *)(void)'
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181813
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
так, вроде разобрался, теперь возникает ошибка при вызове этого указателя...
у меня функция
Код: plaintext
1.
void ClinksDlg::next_atom(void (ClinksDlg::*pfun)())
как его вызвать?
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181814
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnпри передаче в функцию выдает сл. ошибку
cannot convert parameter 1 from 'void (__thiscall ClinksDlg::* )(void)' to 'void (__cdecl *)(void)'

Что Вы пытаетесь сделать, если примеры, то у меня оба работают.
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181824
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnтак, вроде разобрался, теперь возникает ошибка при вызове этого указателя...
у меня функция
Код: plaintext
1.
void ClinksDlg::next_atom(void (ClinksDlg::*pfun)())
как его вызвать?

какую ошибку, как Вы вызываете?
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181826
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ну как я понял из примера, я вызываю вот так:
Код: plaintext
(ClinksDlg::*pfun)();
а ошибку он выдает:
syntax error : '<tag>::*'
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181828
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnну как я понял из примера, я вызываю вот так:
Код: plaintext
(ClinksDlg::*pfun)();
а ошибку он выдает:
syntax error : '<tag>::*'

попробуйте просто (*pfun)();
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181829
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
когда печатаете ClinksDlg:: у Вас появляется выпадающий список принадлежащий ClinksDlg, там разве есть что-то похожее на pfun ??
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181830
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а если так, то возникает аж 2 ошибки
error C2171: '*' : illegal on operands of type 'void (__thiscall ClinksDlg::* )(void)'
error C2064: term does not evaluate to a function taking 0 arguments
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181831
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
можно это фрагмент кода поглядеть?
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181833
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Все разобрался, спасибо вам большое, добрый человек.
написал просто
pfun;
вроде заработало...
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181835
Tubrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnВсе разобрался, спасибо вам большое, добрый человек.
написал просто
pfun;
вроде заработало...

и что? ф-ия вызывается?

может хотябы pfun();
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181839
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
так, поторопился, функция не вызывается, но если ставить скобки то выдает ошибку
term does not evaluate to a function taking 0 arguments
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34181840
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в случае когда просто
pfun;
то эта строка вовсе игнорируется
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34182158
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnв случае когда просто
pfun;
то эта строка вовсе игнорируется

Есстественно, надо указываеть параметры, даже если их нет - пустые скобки.

При вызове метода класса, надо вызываеть с указанием объекта.
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34182712
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так в том и дело, что когда вызываю со скобками то ошибку выдает...
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34182776
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnТак в том и дело, что когда вызываю со скобками то ошибку выдает...

Приведи конечный результат и ошибку
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34182779
Barlone
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psysln
Код: plaintext
1.
void ClinksDlg::next_atom(void (ClinksDlg::*pfun)())
Это таки указатель на член класса. Чтобы вызвать надо иметь экземпляр этого класса.
Код: plaintext
1.
SomeClinkDlg.*pfun()
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34182960
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вообщем отработало вот так:
Код: plaintext
1.
ClinksDlg obj;
(obj.*pfun)();
только вопрос, это нормально каждый раз создавать объект класса?
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34183010
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnвообщем отработало вот так:
Код: plaintext
1.
ClinksDlg obj;
(obj.*pfun)();
только вопрос, это нормально каждый раз создавать объект класса?


Здрасте! А зачем вы тогда используете нестатическую функцию-метод? Методы класса работают в рамках своих данных. Если функция не обрабатывает никакие данные класса, то нафига она находится в составе класса. Если она не обрабатывает данные, но по логике вещей, ее лучше бы было внести в класс, то сделайте ее статической. Тогда можно будет вызывать и без объекта.

Вопрос не в "нормально", а предпологатся, что вы будете давать не какой-нибудь класс, а именно тот, для которого предназначена данная операция.
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34183128
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
да в этом и проблема, все переменные объявленные в секции приват сбрасываются, после вызова этого указателя.
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34183162
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnда в этом и проблема, все переменные объявленные в секции приват сбрасываются, после вызова этого указателя.

Естественно, у тебя же новый объект. Ты должен указывать используемый объект
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34183170
psysln
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а где его взять то?
...
Рейтинг: 0 / 0
как созжать указатель на функцию
    #34183178
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
psyslnа где его взять то?

Создать и хранить. Чтобы он не удалялся при выходе из функции он должен распологаться более глобально. Или вообще быть глобальным, или внутри другого класса, который использует этот.
...
Рейтинг: 0 / 0
25 сообщений из 53, страница 1 из 3
Форумы / C++ [игнор отключен] [закрыт для гостей] / как созжать указатель на функцию
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]