Функции. Объявление и определение функций
Функция – это именованная последовательность описаний и операций, выполняющая законченное действие
- может принимать параметры и возвращать значения
- должна быть объявлена и определена. Объявление должно находиться по тексту раньше точки ее вызова
Объявление функции – задает тип возвращаемого значения, ее имя и список передаваемых параметров. Определение содержит, кроме объявления, тело функции.
формат: [класс] тип имя ([список параметров]) {тело функции}
Класс задает область видимости функции:
extern – глобальная видимость
static – видимость модуля (локальная)
Тип может быть любым кроме массива и функции. Если функция не должна возвращать значения, указывают тип void.
Список параметров определяет величины, которые требуется передать в функцию при ее вызове. Элементы списка параметров разделяются запятыми. Для каждого параметра указывается имя и тип. В объявлении, определении, вызове типы и порядок параметров для одной и той же функции должны совпадать.
Встроенные функции:
модификатор inline – рекомендует компилятору вместо обращения к функции подставить ее код в точку вызова
(inline int funcl();)
Вызов функции:
int sum(int,int);
int main()
{int a=2, b=3, c;
c=sum(a,b); return 0;}
int sum(int x, int y)
{return x+y;}
Использование статических локальных переменных:
void func(int a)
{int b=0;
static int c=0;
cout<<++a<<++b<<++c<<endl;}
void main()
{func(3); func(4);}
Способы обмена данными между функциями. Глобальные переменные. Возвращаемое значение. Параметры функции. Передача массивов в качестве параметров. Параметры со значениями по умолчанию.
Способы взаимодействия функций:
- через глобальные переменные
- через возвращаемое значение
Механизм возврата из функции в вызывающую ее функцию реализуется оператором: return [выражение];
- через параметры функции
Формальные параметры – перечисленные в заголовке описания функции.
Фактические параметры – указанные при вызове функции.
При вызове:
а) вычисляются выражения стоящие на месте аргументов
б) выделяется память под формальные параметры и каждому присваивается значение соответствующего аргумента.
3 способа передачи параметра:
- по значению (функция получает копию значения аргументов)
- по адресу (функции передаются копии адресов аргументов)
- по ссылке 9передается адрес указанного при вызове параметра, а внутри функции обращения к параметру неявно разадресовываются)
void func(int i, int *j, int &k)
{cout<<++i<<++(*j)<<++k<<endl;}
void main()
{int a=1, b=2, c=3;
func(a, &b, c);
cout<<a<<b<<c;}
int func(const char*);
Параметры со значениями по умолчанию:
int f1(int a, int b=0);
f1(1,2); f1(100);
void f2( int i, int j=100, char *k=NULL);
f2(10); f2(4,5); f2(4,10,”Vasia”);
Рекурсивные функции. Функция main().
-рекурсивной называется функция, которая вызывает саму себя
n!=n*(n-1)!; 0!=1; 1!=1
long func(long n)
{if (n==0 || n==1) return 1;
return (n*func(n-1));}
Функция main():
1) тип main()
2) тип main(int argc, char *argv[])
int argc – количество параметров
char *argv[] – текстовое описание параметров
тип – void или int
Перегрузка функций.
Перегрузка функций - использование нескольких функций с одним и тем же именем, но с различными параметрами.
- компилятор определяет, какую именно функцию требуется вызвать, по типу фактических параметров (аргументов).
Если точного соответствия аргументов и параметров перегруженной функции не найдено:
1) производится попытка преобразования коротких типов в более длинные в соответствии с общими правилами (bool, char=>int; float=>double)
2) выполняется стандартное преобразование типов (int=>double, указатели=>void)
3) преобразование типов заданное пользователем
Неоднозначность может появиться:
- при преобразовании типов аргументов
- при использовании параметров-ссылок
- при использовании параметров со значениями по умолчанию
Шаблоны функции.
Шаблон – средство параметризации.
С помощью шаблонов функции можно определить алгоритм, который будет применяться к данным различных типов, а конкретный тип данных передается функции в виде параметра на этапе компиляции.
формат:
teamplate <class Type> заголовок функции {тело функции}
Сортировка методом выбора:
template <class T> void sort(T *b, int n)
{for(int i=0; i<n-1; i++)
{int min=i;
for(int j=i+; j<n; j++)
{if(b[j]<b[min]) min=j;}
T a=b[i];
b[i]=b[min];
}
}
Вызов шаблона:
const int n=20;
int b[n];
sort (b, n);
……..
double a[5];
sort(a, 5);
20)Директивы препроцессора. Директива #include. Директива #define. Директива #undef.
Препроцессором называется первая фаза компилятора, на которой исходный текст программы преобразуется в соответствии со специальными инструкциями, содержащимися в тексте программы.
- инструкции препроцессора называются директивами
- директива препроцессора должна начинаться с символа #
Директива #include:
- директива #include <имя файла> вставляет содержимое указанного файла в ту точку исходного файла, где она записана
- #include “имя файла” – поиск в каталоге, содержащем исходный файл
- заголовочные файлы обычно имеют расширение .h и могут содержать:
а) определения типов, констант, встроенных функций, шаблонов, перечислений
б) объявления функций, данных, имен, шаблонов
в) пространства имен
г) директивы препроцессора
д) комментарии
Директива #define:
- директива #define определяет подстановку в тексте программы
- используется для определения:
а) символических констант
#define имя текст_подстановки
б) макросов
#define имя(параметр) текст_подстановки
в) символов, управляющих условной компиляцией
#define имя
Примеры:
#define VERSION1
#define VASIA “Василий Иванович”
#define MAX(x, y) ((x)>(y)?(x):(y))
#define MUX
Использование макросов:
- вызов макроса
y=MAX(sum1, sum2) будет заменен на
y=((sum1)>(sum2)?(sum1):(sum2))
- отсутствие круглых скобок может привести к неправильному порядку вычисления
неправильный вариант:
#define sqr(x) (x*x)
sqr(y+1) (y+1*y+1)
правильный вариант:
#define sqr(x) ((x)*(x))
sqr(y+1) ((y+1)*(y+1))
Директива #undef:
#undef имя
- удаляет определение символа, введенного директивой #define