Указатели сами по себе очень полезны в работе, но в то же время коваврны, потому что с ними нужно быть очень аккуратным, иначе не избежать утечки памяти. Ниже рассмотрено как можно применять указатели к функциям. Предположим, что у нас есть декларированные функции:
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);
На этом закончу. Если что, то исходник можно скачать здесь.