C++. Указатели на функции, массивы указателей на функции

Указатели сами по себе очень полезны в работе, но в то же время коваврны, потому что с ними нужно быть очень аккуратным, иначе не избежать утечки памяти. Ниже рассмотрено как можно применять указатели к функциям. Предположим, что у нас есть декларированные функции:

int f1(int); int f2(int); int f3(int);

Тогда можно объявить указатель:

int (*p) (int);

Скобки здесь обязательны так как тогда компилятор воспримет это выражение так:

int* p(int);

Ну а это объявление функции с возвращаемым типом типа указатель. Продолжим.
Теперь, ему можно присвоить ссылку на одну из функций:
 
p = f1;

Если прописать так,

p = f1();

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

(*p) (16); // p (16); Так тоже работает

Стоит отметить, что при объявлении указателей на функцию, необходимо соблюдать согласованность типов между указателями и функциями, например так будет некорректно:
 
int (*p) (); // Это равнозначно вырыжению int (*p) (void);

А это уже несогласованность!
Есть еще один нюанс. Предположим, что функция декларирована с аргументами по-умолчанию
 
int f4(int n = 0);

И казалось можно написать так

int (*p) (int);
p = f4;
p ();

И я получаю ошибку компиляции

error C2198: 'int (__cdecl *)(int)' : too few arguments for call

Поэтому нужно будет передать конкретное значение

p (16);

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

template <class T>
T getme(T a, T b) {

       return (a>b?a:b);
}


Тогда при объявлении указателя будет опрелен тип функции getme()
 
char (*tpl) (char, char);
tpl = getme;
cout << "from template function getme() " << tpl ('a', 'b') << endl;


Для удобства работы с указателями можно определить синоним указателей на функцию, например

typedef int (*F) (int); // Сие эквивалентно выражению int (*) int;

Таким образом мы получили синоним указателей - F. Далее с ним работаем вот так

F p; // Сие эквивалентно выражению int (*p) int;

Так мы объявили указатель на функции, ну а дальше по аналогии

p = f1;
p (16);

Теперь рассмотрим массив указателей на функции. Здесь ничего сложного, итак, объявим сие массив:

int (*pm[]) (int) = {f1, f2, f3};

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

(*pm[0]) (16);

На этом закончу. Если что, то исходник можно скачать здесь.