|
|
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
помогите, как мне создать указатель на функцию и передать его в качестве параметра другой ф-ции и там вызвать по этому указателю функцию ??? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.12.2006, 23:46 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
Указатели на функции Указатели на функции[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. Проанализируем эту программу подробно. В первую очередь рассмотрим объявление указателя p в main(): Код: plaintext Это объявление сообщает компилятору, что 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 В этом случае вводить в программу дополнительный указатель 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. Введите два значения или две строки. тест тест Проверка строк на равенство. Равны Введите два значения или две строки. 0123 123 Проверка значений на равенство. Равны Сравнение строк 0123[2] и 123 показывает равенство их значений. ---------- [1]Иногда их называют просто указателями функций. Но следует помнить, что в языках программирования под этим термином подразумевается также средство обращения к подпрограмме-функции или встроенной функции, имеющее конструкцию <имя-функции> (<список-аргументов>). [2]Обратите внимание, что в языке С нулем начинаются восьмеричные константы. Если бы эта запись была в выражении, то 0123 не было бы равно 123. Однако здесь функция atoi() обрабатывает это число как десятичное. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 00:00 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
при передаче в функцию выдает сл. ошибку cannot convert parameter 1 from 'void (__thiscall ClinksDlg::* )(void)' to 'void (__cdecl *)(void)' ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 00:28 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
так, вроде разобрался, теперь возникает ошибка при вызове этого указателя... у меня функция Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 00:46 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnпри передаче в функцию выдает сл. ошибку cannot convert parameter 1 from 'void (__thiscall ClinksDlg::* )(void)' to 'void (__cdecl *)(void)' Что Вы пытаетесь сделать, если примеры, то у меня оба работают. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 00:51 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnтак, вроде разобрался, теперь возникает ошибка при вызове этого указателя... у меня функция Код: plaintext 1. какую ошибку, как Вы вызываете? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:09 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
ну как я понял из примера, я вызываю вот так: Код: plaintext syntax error : '<tag>::*' ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:14 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnну как я понял из примера, я вызываю вот так: Код: plaintext syntax error : '<tag>::*' попробуйте просто (*pfun)(); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:19 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
когда печатаете ClinksDlg:: у Вас появляется выпадающий список принадлежащий ClinksDlg, там разве есть что-то похожее на pfun ?? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:22 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
а если так, то возникает аж 2 ошибки error C2171: '*' : illegal on operands of type 'void (__thiscall ClinksDlg::* )(void)' error C2064: term does not evaluate to a function taking 0 arguments ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:22 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
можно это фрагмент кода поглядеть? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:24 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
Все разобрался, спасибо вам большое, добрый человек. написал просто pfun; вроде заработало... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:26 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnВсе разобрался, спасибо вам большое, добрый человек. написал просто pfun; вроде заработало... и что? ф-ия вызывается? может хотябы pfun(); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:33 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
так, поторопился, функция не вызывается, но если ставить скобки то выдает ошибку term does not evaluate to a function taking 0 arguments ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:45 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
в случае когда просто pfun; то эта строка вовсе игнорируется ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 01:51 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnв случае когда просто pfun; то эта строка вовсе игнорируется Есстественно, надо указываеть параметры, даже если их нет - пустые скобки. При вызове метода класса, надо вызываеть с указанием объекта. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 09:41 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
Так в том и дело, что когда вызываю со скобками то ошибку выдает... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 12:01 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnТак в том и дело, что когда вызываю со скобками то ошибку выдает... Приведи конечный результат и ошибку ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 12:15 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psysln Код: plaintext 1. Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 12:16 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
вообщем отработало вот так: Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 12:58 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnвообщем отработало вот так: Код: plaintext 1. Здрасте! А зачем вы тогда используете нестатическую функцию-метод? Методы класса работают в рамках своих данных. Если функция не обрабатывает никакие данные класса, то нафига она находится в составе класса. Если она не обрабатывает данные, но по логике вещей, ее лучше бы было внести в класс, то сделайте ее статической. Тогда можно будет вызывать и без объекта. Вопрос не в "нормально", а предпологатся, что вы будете давать не какой-нибудь класс, а именно тот, для которого предназначена данная операция. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 13:07 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
да в этом и проблема, все переменные объявленные в секции приват сбрасываются, после вызова этого указателя. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 13:32 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnда в этом и проблема, все переменные объявленные в секции приват сбрасываются, после вызова этого указателя. Естественно, у тебя же новый объект. Ты должен указывать используемый объект ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 13:39 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
а где его взять то? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 13:40 |
|
||
|
как созжать указатель на функцию
|
|||
|---|---|---|---|
|
#18+
psyslnа где его взять то? Создать и хранить. Чтобы он не удалялся при выходе из функции он должен распологаться более глобально. Или вообще быть глобальным, или внутри другого класса, который использует этот. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.12.2006, 13:42 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=34183170&tid=2029878]: |
0ms |
get settings: |
6ms |
get forum list: |
12ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
155ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
42ms |
get tp. blocked users: |
1ms |
| others: | 196ms |
| total: | 426ms |

| 0 / 0 |
