No Image

Указатель на функцию c в качестве параметра

СОДЕРЖАНИЕ
0 просмотров
11 марта 2020

Как там все это объявить и после получить возвращаемое значение?

6 ответов 6

Передаем в функцию и используем:

Просто несколько примеров

А дальше ищи доку по указателям на функции.

С помощью boost::function так. Или std::function в С++11 так. Способ с голыми указателями также применим, но у функциональных объектов возможностей гораздо больше.

Имя функции – ее адрес. Для объявления типа копайте в сторону typedef. Можно еще почитать

Всё ещё ищете ответ? Посмотрите другие вопросы с метками c++ функции или задайте свой вопрос.

Похожие

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

дизайн сайта / логотип © 2019 Stack Exchange Inc; пользовательское содержимое попадает под действие лицензии cc by-sa 4.0 с указанием ссылки на источник. rev 2019.12.20.35703

Указатели на функции

К ак уже обсуждалось ранее функции – это набор команд, которые расположены в соответствующей области памяти. Вызов функции – это сохранение состояния, передача аргументов и переход по адресу, где располагается функция. В си есть возможность создавать указатели на функции. Указатели на функции позволяют упростить решение многих задач. Совместно с void указателями можно создавать функции общего назначения (например, сортировки и поиска). Указатели позволяют создавать функции высших порядков (функции, принимающие в качестве аргументов функции): отображение, свёртки, фильтры и пр. Указатели на функции позволяют уменьшать цикломатическую сложность программ, создавать легко масштабируемые конструкции. Рассмотрим пример. Создадим функцию и указатель на эту функцию

Синтаксис объявления указателей на функцию
(* )( );

В этом примере мы создали функцию отображения, которая применяет ко всем элементам массива функцию, которая передаётся ей в качестве аргумента. Когда мы вызываем функцию map, достаточно просто передавать имена функций (они подменяются указателями). Запишем теперь функцию map, которая получает в качестве аргумента массив типа void:

Вот где нам понадобились указатели типа void. Так как map получает указатель на функцию, то все функции должны иметь одинаковые аргументы и возвращать один и тот же тип. Но аргументы функций должны быть разного типа, поэтому мы делаем их типа void. Функция map получает указатель типа void (*)(void*), поэтому ей теперь можно передавать любую из четырёх функций.
Пример другой функции: функция filter получает указатель на массив и возвращает размер нового массива, оставляя в нём только те элементы, для которых переданный предикат возвращает логическую истину (предикат – функция, которая возвращает истину или ложь). Сначала напишем для массива типа int:

Читайте также:  Escape dead island обзор

Теперь для массива типа void

Ещё одна функция – свёртка. Она получает в качестве аргументов массив и функцию от двух аргументов. Эта функция действует следующим образом: сначала она применяется к первым двум аргументам, затем она применяется к третьему аргументу и результату предыдущего вызова, затем к четвёртому аргументу и результату предыдущего вызова и т.д. С помощью свёртки можно, например, найти сумму всех элементов массива, максимальный элемент массива, факториал числа и т.п.

Последний пример: функция сортировки вставками для массива типа void. Так как тип массива не известен, то необходимо передавать функцию сравнения.

Массив указателей на функции

М ассив указателей на функции определяется точно также, как и обычный массив – с помощью квадратных скобок после имени:

Точно также можно было создать массив динамически

Часто указатели на функцию становятся громоздкими. Работу с ними можно упростить, если ввести новый тип. Предыдущий пример можно переписать так

Ещё один пример: функция any возвращает 1, если в переданном массиве содержится хотя бы один элемент, удовлетворяющий условию pred и 0 в противном случае.

qsort и bsearch

В библиотеке stdlib си имеется несколько функций, которые получают в качестве аргументов указатели на функции. Функция qsort получает такие же аргументы, как и написанная нами функция insertionSort: массив типа void, размер массива, размер элемента и указатель на функцию сравнения. Давайте посмотрим простой пример – сортировка массива строк:

Функция bsearch проводит бинарный поиск в отсортированном массиве и получает указатель на функцию сравнения, такую же, как и функция qsort. В случае, если элемент найден, то она возвращает указатель на этот элемент, если элемент не найден, то NULL.

Обновл. 31 Дек 2019 |

Из урока №80 мы узнали, что указатель — это переменная, которая содержит адрес другой переменной. Указатели на функции аналогичны, за исключением того, что вместо обычных переменных, они указывают на функции!

Читайте также:  Чем отличаются зубные щетки oral b

Указатели на функции

Рассмотрим следующий фрагмент кода:

Идентификатор boo — это имя функции. Но какой её тип? Функции имеют свой собственный l-value тип, в этом случае это тип функции, который возвращает целочисленное значение и не принимает никаких параметров. Подобно переменным, функции также имеют свой адрес в памяти.

Когда функция вызывается (с помощью оператора ()), точка выполнения переходит к адресу вызываемой функции:

Одной из распространённых ошибок является:

Вместо вызова функции boo() и вывода возвращаемого значения мы, совершенно случайно, отправили функцию boo непосредственно в std::cout. Что произойдёт в этом случае?

Результат на моём компьютере:

У вас может быть и другое значение, в зависимости от того, в какой тип данных ваш компилятор решит конвертировать указатель на функцию. Если ваш компьютер не вывел адрес функции, то вы можете заставить его это сделать, конвертируя boo в указатель типа void и отправляя его на вывод:

Так же, как можно объявить неконстантный указатель на обычную переменную, так же можно объявить и неконстантный указатель на функцию. Синтаксис создания неконстантного указателя на функцию, пожалуй, один из самых «уродливых» в C++:

В примере выше, fcnPtr — это указатель на функцию, которая не имеет параметров и возвращает целочисленное значение. fcnPtr может указывать на любую другую функцию, соответствующую этому типу.

Скобки вокруг *fcnPtr необходимы для соблюдения приоритета операций, в противном случае int *fcnPtr() будет интерпретироваться как предварительное объявление функции fcnPtr , которая не имеет параметров и возвращает указатель на целочисленное значение.

Для создания константного указателя на функцию используйте const после звёздочки:

Если вы поместите const перед int, то это будет означать, что функция, на которую указывает указатель, возвращает const int.

Присваивание функции указателю на функцию

Указатель на функцию может быть инициализирован функцией (и неконстантному указателю на функцию тоже можно присвоить функцию):

Одна из распространённых ошибок, которую совершают новички:

Здесь мы фактически присваиваем возвращаемое значение из вызова функции doo() для fcnPtr , чего мы не хотим делать. Мы хотим, чтобы fcnPtr содержал адрес функции doo(), а не возвращаемое значение из doo(). Поэтому скобки не нужны.

Читайте также:  Ставим звук с видео

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

В отличие от фундаментальных типов данных, C++ неявно конвертирует функцию в указатель на функцию, если это необходимо (поэтому вам не нужно использовать оператор адреса & для получения адреса функции). Однако, C++ не будет неявно конвертировать указатель на функцию в указатель типа void или наоборот.

Вызов функции через указатель на функцию

Вы также можете использовать указатель на функцию для вызова самой функции. Есть два способа сделать это. Первый — через явное разыменование:

Второй — через неявное разыменование:

Как вы можете видеть, способ неявного разыменования выглядит так же, как и обычный вызов функции, так как обычные имена функций являются указателями на функции! Однако некоторые старые компиляторы могут не поддерживать способ неявного разыменования, с современными компиляторами всё поддерживается.

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

Передача функций в качестве аргументов другим функциям

Одна из самых полезных вещей, которую вы можете сделать с указателями на функции — это передать функцию в качестве аргумента другой функции. Функции, используемые в качестве аргументов для других функций, называются функциями обратного вызова.

Рассмотрим случай: вы пишете функцию для выполнения определённого задания (например, сортировки массива), но вы хотите, чтобы пользователь мог определить, каким образом выполнять эту сортировку (например, по возрастанию или по убыванию). Рассмотрим более подробно этот случай.

Все алгоритмы сортировки работают по одинаковой схеме: алгоритм выполняет итерацию по списку чисел, сравнивает пары чисел и меняет их местами, исходя из результатов этих сравнений. Следовательно, изменяя алгоритм сравнения чисел, мы можем изменить способ сортировки, не затрагивая остальные части кода.

Комментировать
0 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
Adblock detector