Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Konspekt_S__Chast_2.doc
Скачиваний:
31
Добавлен:
09.02.2015
Размер:
1 Mб
Скачать

Передача функций в качестве параметров

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

cout << C << endl; // Cэто функция из предыдущего параграфа

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

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

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

Рассмотрим пример:

double add (double a, double b)

{

return a + b;

}

double mul (double a, double b)

{

return a * b;

}

typedef double (*f_Ptr) (double, double);

double oper (f_Ptr F, double a, double b)

{

return F (a, b);

}

int main ()

{

cout << oper (add, 20, 30) << endl; // 50

cout << oper (mul, 20, 30) << endl; // 600

return 0;

}

В этом примере имеется некоторая универсальная функция oper, возвращающая значение вычисленной функцииF для заданных значенийa и b. ФункцияF, которую необходимо вычислить, передается в функциюoperчерез параметр этой функции. Ключевые элементы этого алгоритма выделены красным цветом. Для того, чтобы параметрFфункцииoperмог принимать в качестве аргумента другую функцию, с помощью инструкцииtypedefопределяется тип данных указателяf_Ptrна функции, возвращающие значение типаdoubleи имеющие два параметра типаdouble.

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

Несколько слов об инструкции typedef. С помощью этой инструкции можно определять новые типы данных и переопределять уже имеющиеся. Например: довольно утомительно в тексте программы многократно использовать название типа данныхunsigned short. С помощью инструкцииtypedefможно упростить набор текста программы:

typedef unsigned short UnS;

Теперь везде в тексте программы можно использовать вместо типа unsigned short тип UnS.

Однако увлекаться такими “переименованиями” не следует. В основном инструкция typedef используется при определении новых пользовательских типов данных.

Встраиваемые функции (inline - функции)

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

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

inline int ReadInt(char *S) // Ввод целых значений по текстовому запросу S

{

cout << S;

int I;

cin >> I;

return I;

}

{

……..

int Vozrast = ReadInt (“Сколько Вам лет? ”);

……..

int Kurs = ReadInt (“На каком курсе Вы учитесь? ”);

……..

int Ocenka = ReadInt (“Сколько у Вас отличных оценок в последней сессии? ”);

……..

}

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

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

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

  • рекурсии;

  • циклов, переключателей, инструкций goto;

  • статических (static) переменных.

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]