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

Один из вопросов программирования, могущий возникнуть у изучающего С++, — это вопрос создания массива указателей на функции.
Иногда удобно использовать массивы функций. В самом примитивном случае можно вызывать функции в случайном порядке или задавать цепочки вызовов в нужном порядке. Непосредственно массив функций именно как массив — создать нельзя. Тем не менее, можно создавать указатели на функции и сохранять набор указателей в массиве указателей. Есть, правда, специальные обёртки, решающие подобное возникновение проблемы путём обхода использования указательных переменных, но эта статья изначально предполагалась как статья об указателях на функции. Иногда указатели на функции тоже может быть удобно использовать. Поэтому дальше будет описано как создавать массив указателей на функции, а не как использовать обёртки для решения подобных потребностей.
Пример кода:


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


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

Смотрим на 13-ю строчку кода.

arr является массивом из 3 указателей и при этом каждый из трёх указателей указывает на функцию с пустым списком формальных параметров (пустые скобки), и тип всей этой сущности — void соответствует типу каждой ячейки массива, а поскольку каждая ячейка содержит функцию, то этот тип обозначает тип функций, хранимых в массиве, т. е. массив хранит функции, тип у которых void.

Смотрим на 15-ю строчку кода. Там мы вытаскиваем значение из массива и использованием круглых скобок задействуем вытащенное значение как функцию. Не забываем, что индексация массивов начинается с нуля, и поэтому то, что мы пишем 2 в квадратных скобках в месте обращения к ячейке массива — будет обозначать третий индекс массива. (0,1,2) — двойка на третьей позиции. Так как в массиве расположены не самые обычные значения, а адреса функций, то и обращаемся мы к значениям не как к обычным значениям, а как к функциям, после чего и происходит вызов той функции, к которой мы обратились задействовав указатель, хранящийся в массиве.

Если вы легко разруливаете работу с параметрами функций, поймёте массив указателей, то эта тема может показаться вам очень даже лёгкой. Массив указателей на функции по сути ничем не отличается от обычного массива значений. Разве что обычные значения вызывать как функции не нужно, а массив — он и есть массив.
Добавлено 15.11.2021
С массивом указателей на функции, возвращающие неуказательные типы, вроде как должно было стать что-нибудь да понятно. А как поместить в массив функции, возвращающие указатели на указатели? Такое можно проворачивать, но надо обязательно учитывать три вещи:
указатели — это не массивы, не функции, поэтому нельзя будет в ячейку запихать указатель на функцию, надо только саму функцию
следует понимать, что могут быть проблемы с очисткой памяти: очень легко потерять связь с выделенной памятью, поэтому лучше всего запоминать адреса в отдельные указатели
надо хорошо понимать, где массив [], а где не массив,
ведь для удаления из памяти массива надо делать delete [], а для удаления немассива delete

Особое внимание обратите на объявление массива: поскольку массив содержит значения int**, объявляем, что нам нужен тип int**, после чего показываем, что будем имет дело с массивом на указатели, хранящим указатели на функции. При этом явно указываем идентификатору, что он указатель.

5 комментариев на «“Указатели. Массив указателей на функции”»

  1. DanMan:

    А каким образом аргумент передавать в функцию???

    • Все функции внутри массива должны быть определены с одинаковыми аргументами.

  2. Да, забыть что в месте запуска функций мы используем круглые скобки — это жирный баг) всегда помните об этом))

  3. alex:

    Первый пример совсем не соберётся, т.к. функции названы не верно
    Последний пример — в строке 15 — непонятно, зачем разыменовывать звёздочкой, если взятие элемента по номеру [2] — его разыменует и получим указатель.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/denis-kolisnichenko/rukovodstvo-po-komandam-i-shell-programmirovaniu-v-linux/?lfrom=15589587
Яндекс.Метрика