Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции за I семестр конспект Гуревича для C++ B....doc
Скачиваний:
11
Добавлен:
21.11.2018
Размер:
1.3 Mб
Скачать

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

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

Рассмотрим методику работы с указателями на функции.

1. Как и любой объект языка Си, указатель на функции необходимо декларировать. Формат объявления указателя на функции следующий:

тип (*переменная-указатель)(список параметров);

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

Например, объявление вида:

double (*p_f )(char, double);

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

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

переменная-указатель = ID_функции;

Например, имеется функция с прототипом: double f1(char, double); тогда операция

p_f = f1;

установит указатель p_f на данную функцию.

Идентификатор функции может быть присвоен указателю и по-другому:

double f1(char C, double D){

... // тело функции f1

}

void FunOut(double (*p_f )(char, double)){

... // тело функции FunOut

}

void main(){

... // тело функции main

FunOut(f1);

... // тело функции main

}

Здесь при вызове функции FunOut в нее передается аргумент - указатель на функцию f1, который присваивается параметру p_f .

3. Вызов функции после установки на нее указателя выглядит так:

(*переменная-указатель)(список аргументов);

или

переменная-указатель (список аргументов);

После таких действий кроме стандартного обращения к функции:

Id_функции(список аргументов);

появляется еще два способа вызова функции:

(*переменная-указатель)(список аргументов);

или

переменная-указатель (список аргументов);

Последняя запись справедлива, так как p_f также является адресом начала функции в оперативной памяти.

Например, в теле вышеприведенной функции FunOut вызов функции по указателю может выглядеть так:

double zz=p_f('@', 3.14159);

В вышеприведенном примере тогда будет вызвана функция f1, причем C будет присвоено значение - символ @ , а D - 3.14159 .

18. Работа с динамической памятью

18.1. Динамическое выделение и освобождение памяти.

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

Динамическое (т.е. осуществляемое в процессе работы программы) выделение памяти означает:

  1. поиск свободного (т.е. не занятого пока никаким объектом) участка памяти требуемого размера;

  2. объявление его занятым (чтобы никакая последующая операция выделения памяти не назначила его другому объекту);

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

Динамическое выделение памяти называется также ее захватом.

Если в процессе работы динамически выделенная память оказывается больше не нужной, рекомендуется ее освободить, т.е. объявить доступной для других возможных операций выделения памяти. При завершении работы программы вся выделенная ей память освобождается автоматически.

Для работы с динамической памятью в С++ введены две операции:

захват памяти - new,

освобождение захваченной ранее памяти - delete.