рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

УКАЗАТЕЛЬ НА ФУНКЦИЮ.

УКАЗАТЕЛЬ НА ФУНКЦИЮ. - раздел Философия, Лекция 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);

В процессе трансляции будет восстановлен исходный вид объявления

 

– Конец работы –

Эта тема принадлежит разделу:

Лекция 1. Объектно-ориентированное программирование – это новый подход к программированию. Объектно- ориентированные языки обладают свойством

ВВЕДЕНИЕ... Приступая к изучению более сложных конструкций языка С следует прежде всего повторить тот материал который был...

Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: УКАЗАТЕЛЬ НА ФУНКЦИЮ.

Что будем делать с полученным материалом:

Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Все темы данного раздела:

Имя_объекта.имя_элемента
x1.real=dim[3].real=1.45;   Класс может иметь столько объектов сколько необходимо, так же как и любая функция. Объекты могут быть любого тип

Имя объекта.имя функции();
Пример: #include<iostream.h> class rec { private: double len; double wid; public: double Len(){ return len/100;}

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

Директивы препроцессора.
  Препроцессор(макропроцессор) - это составная часть стандартного пакета языка Си, которая обрабатывает исходный текст программы до того, как он пройдет через компиля

Включение файлов.
  Директива #include включает в текст программы содержимое указанного файла. Эта директива имеет две формы:   #include "имя файла&

Условная компиляция.
  Условные конструкции препроцессора позволяют компилировать или пропускать часть программы в зависимости от выполнения некоторого условия. Условие может принимать одну из описываемых

ВНУТРЕННЕЕ ПРЕДСТАВЛЕНИЕ ЦЕЛЫХ ТИПОВ ДАННЫХ.
  Беззнаковые данные хранятся в оперативной памяти просто, чтобы узнать какое число хранится в данном байте или в слове необходимо выписать значения всех его битов и считать, что это

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

Аргументы функции main()
  Функция main, с которой начинается выполнение программы на языке СИ, может быть определена с параметрами, которые передаются из внешнего окружения, например, из командной строки. Во

Область действия и область видимости переменных.
  В языке C++ каждая функция это отдельный блок программы. Попасть в тело функции можно только с помощью вызова данной функции, то есть нельзя оператором безусловного перехода goto пе

Модификаторы переменных.
  В языке C++ имеется несколько модификаторов которые изменяют область действия и время жизни переменных     Модификаторы &nb

Модификатор тип_переменной имя_переменной
Все переменные в программе характеризуются не только типом, но и классом памяти. В языке Си существует четыре класса памяти: автоматический (automatic), регистровый(registe

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

ПЕРЕГРУЖЕННЫЕ ФУНКЦИИ.
  Перегрузкой называют практику придания функции более чем одного значения. Этот термин означает, что в коде программы существует две различные по содержанию, но одинаковые по названи

ФУНКЦИИ С ПЕРЕМЕННЫМ ЧИСЛОМ ПАРАМЕТРОВ.
  При вызове функции с переменным числом параметров в вызове этой функции задается любое требуемое число аргументов. В объявлении и определении такой функции переменное число аргумент

Начальные установки графики.
  Перед началом работы с графикой, используется функция initgraph(), которая инициализирует графическую систему загружает графический драйвер и переводит систему в графический режим.

Функция line().
  Функция line() - вычерчивает линию между двумя заданными точками принадлежит библиотеке graphics.h Общий вид вызова: void line(int x1, int y1, int x2, int

Функция lineto().
  Функция lineto() чертит линию от текущей позиции курсора в точку с координатами (x,y)Расположена в библиотеке graphics.h Общий вид вызова функции: void li

Функция circle().
  Функция circle() вычерчивает окружность заданного радиуса из заданного центра. Функция находится в графической библиотеке graphics.h В качестве параметров передаются коорди

Функция rectangle ()
  Назначение функции rectangle () в вычерчивании прямоугольника. Функция rectangle () вычерчивает прямоугольник, используя при этом текущие тип линии, толщину и цвет

ФОРМАТИРОВАННЫЙ ПОТОКОВЫЙ ВВОД-ВЫВОД.
  В примерах программ рассмотренных выше, использовались операции помещения в поток << , например в стандартный поток вывода cout и операцией извлечения из потока >>, прим

Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • Популярное
  • Облако тегов
  • Здесь
  • Временно
  • Пусто
Теги