
- •Оглавление
- •Лекция 1 Тема: Процесс построения программы.
- •Директивы #include
- •Комментарии
- •Лекция 2 Тема: Представление данных в с. Литералы
- •Встроенные типы данных
- •Типизированные константы
- •Операции и выражения
- •Семантика операций
- •Операции присваивания сама возвращает значение, что позволяет, например, написать:
- •Приведение типа
- •Смешанные выражения.
- •Поразрядные операции и сдвиги.
- •Инкремент и декремент
- •Запятая
- •Лекция 3 Управляющие конструкции с.
- •Условный оператор if... Else
- •Оператор выбора switch
- •1. Цикл while
- •2. Цикл do—while
- •3. Цикл for
- •Операторы прерывания блока
- •Escape-последовательности.
- •Лекция5 Функции
- •Задание
- •Лекция 6 Массивы и указатели
- •Последнее эквивалентно
- •Указатель на функцию
- •Лекция 7 Строки.
- •Лекция 8 Типы, определяемые пользователем.
- •Переименование типов.
- •Перечислимые типы
- •Структуры.
- •Объединения.
- •Лекция 9 Файлы.
- •Лекция 10 Связанные структуры.
- •Новый элемент Конец стека Начало стека
- •Лекция 11 Директивы препроцессора
- •Условная компиляция
- •Типичное применение препроцессорных директив Предотвращение включения файлов
- •Переключение разделов кода
- •Отладочные диагностические сообщения
- •Лекция 12 Тема: Состав проекта.
- •Лекция 13 Тема: Объектно-ориентированное программирование.
- •Лекция 14 Тема: Создание классов и их потомков. Перегрузка функций.
- •Лекция 15 Тема: Создание новых компонентов.
Указатель на функцию
Ранее функция рассматривалась как минимальный исполняемый модуль программы, обмен данными с которым происходит через набор параметров функции и с помощью возвращаемых значений.
Функция в С++ - это один из производных типов. Необходимость в таком типе связана с задачами , в которых функция (или ее адрес) выступает в качестве параметра другой функции или в качестве возвращаемого значения. При описании функции название функции должно иметь тип «указатель на функцию, возвращающую значение конкретного типа». Указатель на функцию как переменная вводится отдельно от определения. Для этого используется конструкция вида:
тип (*имя_указателя) (спецификация_параметров);
Например, запись
int (*p)(void);
определяет указатель-переменную на функции без параметров, возвращаюшие значения типа int.
Запись указателя в скобках существенна, т.к. если записать:
int *p(void); то это будет не определение указателя, а прототип функции без параметров с именем р , возвращающей значение типа int *.
Пусть имеется некоторая функция:
void ShowString(char *s)
{
printf (“%s”,s);
}
/***********************************************
** Главная функция:
int main(void) {
void (*pFunc)(char*); // Объявление указателя на функцию.
pFunc = ShowString; // Инициализация указателя адресом функции.
(*pFunc)("Calling a pointer to function!\n");
return 0;
}
В примере указателю присваивается значение, представленное просто именем функции без скобок со списком параметров. То есть “значение”, представленное именем функции, имеет тот же тип, что и объявленный здесь указатель. Поэтому и вызвать функцию через указатель можно было бы проще:
pFunc("Calling a pointer to function!\n");
Соотношение между указателями и функциями примерно такое же, как между указателями и массивами.
Массивы указателей на функции.
Такие массивы по смыслу не отличаются от массивов других объектов. Объявление:
тип (*имя_массива [размер]) (спецификация_парамеров);
Пример:
int (*p[4]) (char); - здесь p – это массив указателей на функции, каждому их которых можно присвоить адрес любой функции с прототипом вида int имя_функции(char);.
Массив в соответствии с синтаксисом является производным типом. Массив функций создать нельзя, но можно определить массив указателей на функции. Появляется возможность создавать таблицы переходов (или таблицы передачи управления). С их помощью удобно организовать ветвления с возвратом по результатам анализа некоторых условий. Для этого создаются однотипные функции (имеющие одинаковый тип возвращаемого значения и одинаковые спецификации параметров). Вводится индекс, который соответствует количеству ветвей обработки. Каждому условию ставится в соответствие конкретное значение индекса. Тогда по определенному индексу выполняется обращение к определенному элементу массива указателей и вызов соответствующей функции.
Эту схему удобно использовать для организации программ, которыми пользователь управляет с помощью меню.
void act0 (char *name)
{
printf(“%s: Работа завершена!\n”,name);
exit(0);
}
void act1 (char *name)
{
printf(“%s: работа 1!\n”,name);
}
void act2 (char *name)
{
printf(“%s: работа 2!\n”,name);
}
void main()
{
void (*p[])(char *)={act0, act1, act2};
char s[12];
int number;
printf(“\n Введите имя пользователя:”);
scanf(“%s”,s);
printf(“\nВведите номер работы”)
while(1)
{
scanf(“%d”,&number);
p[number] (s);
}
}