Реферат Курсовая Конспект
УКАЗАТЕЛЬ НА ФУНКЦИЮ. - раздел Философия, Лекция 1. Объектно-ориентированное программирование – это новый подход к программированию. Объектно- ориентированные языки обладают свойством Основными Характеристиками Функции Является Тип Возвращаемого...
|
Основными характеристиками функции является тип возвращаемого значения и список типов формальных параметров. Подобно тому, как имена переменных никаким образом не влияют на их тип, имена функций не является частью их типа. Тип функции определяется типом возвращаемого значения и списком типов её формальных параметров. Например, пара функций
char MyF1 (int, int, int*, float);
char MyNew (int MyP1, int MyP2, int* MyP3, float MyP3);
имеют один и тот же тип:
char (int, int, int*, float)
Такая конструкция называется описанием типа функции.
Описание типа функции, которая возвращает указатель на объект типа char:
char * (int, int, int*, float)
Описанию этого типа соответствует, например, функция
char *MyFp (int MyP1, int MyP2, int* MyP3, float MyP3);
Комбинируя знак операции * с именем функции можно получить новую языковую конструкцию:
char (*MyPt1) (int MyP1, int MyP2, int* MyP3, float MyP3);
Это уже не объявление функции. Это определение указателя на функцию! Это объект со следующими характеристиками:
его имя MyPt1,
это указатель на функцию, эта функция должна возвращать значения типа char, список её формальных параметров имеет вид (int,int,int*, float).
Так что это должны быть функции со строго определёнными характеристиками. В нашем случае - это функции типа
char (int, int, int*, float)
Описание типа указателя на функцию, возвращающую указатель на объект типа char с параметрами (int, int, int*, float)
char * (int, int, int*, float)
отличается от описания типа этой функции дополнительным элементом (*):
char * (*) (int, int, int*, float).
Пример определения подобного указателя:
char* (*MyPt2) (int MyP1, int MyP2, int* MyP3, float MyP3);
И опять новый объект:
его имя MyPt2,
это указатель на функцию, эта функция должна возвращать указатель на объекты типа char, список её формальных параметров имеет вид
(int,int,int*, float).
Также можно определить функцию, которая будет возвращать указатель на объект типа void (то есть просто указатель).
Ее вид:
void * (int)
Описанию этого типа соответствует, например, функция
void *malloc (int size);
Эта функция пытается выделить блок памяти размера size и в случае, если это удалось сделать, возвращает указатель на выделенную область памяти. В противном случае возвращается специальное значение NULL. Как распорядиться выделенной памятью - дело программиста. Единственное ограничение заключается в том, что при этом необходимо использовать явное преобразование типа:
#include <stdlib.h>
char *p = NULL;
void NewMemory ()
{
p = malloc(sizeof(char)*1024);// неверно!
p = (char*) malloc(sizeof(char)*1024);
// Требуется явное преобразование типа.
}
Имя массива, если к нему не применяется операция индексации, оказывается указателем на первый элемент массива. Аналогично, имя функции, если к нему не применяется операция вызова, является указателем на функцию.
В нашем случае ранее объявленная функция под именем MyFp приводится к безымянному указателю типа
char * (*) (int, int, int*, float)
К имени функции может быть применена операция взятия адреса. Её применение также порождает указатель на эту функцию. Таким образом, MyFp и &MyFp имеют один и тот же тип.
Инициализировать указатель на функцию можно так:
char* (*MyPt2) (int, int, int*, float) = MyFp;
Очевидно, что функция MyFp() должна быть к этому моменту не только объявлена, но и определена.
Новому указателю на функцию
char* (*MyPt3) (int, int, int*, float);
можно также присвоить новое значение.
Для этого достаточно использовать ранее определённый и проинициализированный указатель:
MyPt3 = MyPt2;
Или адрес ранее определённой функции:
MyPt3 = MyFp;
При этом инициализация и присваивание оказываются корректными лишь при условии, что имеет место точное сопоставление списков формальных параметров и списков формальных значений в объявлениях указателей и функций.
Для вызова функции с помощью указателя использование операции разыменования не обязательно. Полная форма вызова
char* MyPointChar = (*MyPT3)(7,7,NULL,7.7);
имеет краткую эквивалентную форму
char* MyPointChar = MyPT3(7,7,NULL,7.7);
Значением выражения MyPT3 является адрес функции.
Чтобы описать массив указателей на функцию нужно:
char* (*MyPtArray[3]) (int, int, int*, float);
Здесь описан массив указателей из 3 элементов. Инициализация
массива указателей возможна лишь после объявления трёх
однотипных функций:
extern char* MyFF1 (int, int, int*, float);
extern char* MyFF2 (int, int, int*, float);
extern char* MyFF3 (int, int, int*, float);
char* (*MyPtArray[3]) (int, int, int*, float) =
{
MyFF1,
MyFF2,
MyFF3
}; // Инициализация массива указателей.
Вызов функции (например, MyFF3()) с помощью элемента массива указателей можно осуществить следующим образом:
char* MyPointChar = MyPtArray[2](7,7,NULL,7.7);
Указатель на функцию может быть описан как параметр функции:
void MonitorF(int,int,int*,float,char*(*)(int,int,int*,float));
Этому параметру можно присвоить значение (значение по умолчанию):
void MonitorF(int,int,int*,float,char*(*)(int,int,int*,float)=MyFF1);
Используемая для инициализации последнего параметра функция должна быть к моменту инициализации, по крайней мере, объявлена.
Определение функции MonitorF может выглядеть:
#include <assert.h>
/* Заголовочный файл, содержащий макроопределение assert.
Это макроопределение преобразуется в условный оператор if.
Если в ходе проверки значение условного выражения оказывается
равным нулю, то происходит прерывание выполнения программы. */
void MonitorF (
int val1,
int val2,
int* pVal,
float fVal,
char*(*pParF)(int,int,int*,float)
)
{
char* pChar;
assert(pVal != NULL);
assert(pParF != NULL);
//Проверка того, не являются ли указатели пустыми.
pChar = pParF(val1, val2, pVal, fVal);
}
Возможные варианты вызова этой функции:
int MMM;
int* pIval = &MMM;
/*
Указатель pIval используется для инициализации третьего параметра.
*/
MMM = 100;
/*
значение объекта, на который настроен указатель pIval, может быть
изменено в любой момент.
*/
MonitorF(9,9,pIval,9.9);
/*
При вызове используется значение указателя на функцию, присвоенное последнему параметру по умолчанию.
*/
MonitorF(11,11,pIval,11.11,MyFF3);
/* передаём адрес новой функции */
Лекция 10.
Указатель на функцию может также быть типом возвращаемого значения. Объявление подобной функции требует определённого навыка. Начнём с той части объявления, которая содержит имя функции и список её формальных параметров.
ReturnerF(int, int)
Определим теперь тип указателя на функцию, который будет возвращаться функцией ReturnerF(int, int).
char* (*)(int,int,int*,float)
Можно соединить обе части объявления:
char* (*ReturnerF(int, int))(int,int,int*,float);
Получилась матрёшка. Функция с двумя целочисленными параметрами, возвращающая указатель на функцию, которая возвращает указатель на объект типа char и имеет собственный список формальных параметров вида: (int,int,int*,float). Самое сложное - это объявить прототип подобной функции. При определении функции нужно помнить, что она (всего лишь) возвращает указатель на функцию, то есть просто имя функции. Эта функция должна быть предварительно объявлена и определена, а её описание должно соответствовать характеристикам функции ReturnerF.
Такими функциями являются: MyFF1, MyFF2, MyFF3.
Реализация может быть, например, такой:
char* (*ReturnerF(int param1, int param2))(int,int,int*,float)
{
char* (*PointF) (int,int,int*,float);
/*
Это всего лишь указатель на функцию.
*/
if (!param1) return NULL;
switch param2
{
case 1: PointF = MyFF1; break;
case 2: PointF = MyFF2; break;
case 3: PointF = MyFF3; break;
default: PointF = NULL; break;
}
return PointF;
}
Эта функция возвращает адрес функции.
И поэтому самое простое - это вызов функции непосредственно из точки возврата функции ReturnerF:
int val1, val2;
:::::
MyPointChar = (ReturnerF(val1,val2))(7,7,NULL,7.7);
Но существует вероятность возвращения пустого указателя. Так что придётся воспользоваться ранее объявленным указателем на функцию, проверять возвращаемое значение и только потом вызывать функцию по означенному указателю.
MyPtArray[3] = ReturnerF(val1,val2);
if (MyPtArray[3])
{MyPointChar = (MyPtArray[3])(7,7,NULL,7.7);}
/* используется элемент массива указателей */
Если применить typedef-спецификатор. То с его помощью запись указателя на функцию можно сделать компактнее:
typedef char* (*PPFF) (int,int,int*,float);
Здесь надо представлять всё ту же матрёшку. Замещающий идентификатор PPFF располагается внутри определяемого выражения.
Новое объявление старой функции.
PPFF ReturnerF(int, int);
В процессе трансляции будет восстановлен исходный вид объявления
– Конец работы –
Эта тема принадлежит разделу:
ВВЕДЕНИЕ... Приступая к изучению более сложных конструкций языка С следует прежде всего повторить тот материал который был...
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: УКАЗАТЕЛЬ НА ФУНКЦИЮ.
Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов