задание к лекции 3

advertisement
Лекция 3. Функции в языке С++. Перегруженные функции. Область действия переменных и связанные с ней понятия. Создание программ из нескольких модулей. Условная компиляция программ.
ФУНКЦИИ В ЯЗЫКЕ С++
Функция является основным структурным элементом языка С++. Определение
функции имеет следующий синтаксис:
возвращаемый_тип имя_функции(список параметров)
{
тело функции
}
Пример:
long double max_ab(long double a, long double b)
{long double x;
if (a>b) {x=a} else {x=b};
return x;
}
Данная функция возвращает значение максимального из своих двух параметров. Оператор return служит для указания возвращаемого функцией значения (в данном случае –
значения переменной х). На нём исполнение функции заканчивается. Если оператор
return отсутствует, то возвращаемое значение равно 0. Вызов данной функции в программе происходит следующим образом:
long double x=2.71, y=3.14, z;
z=max_ab(x, y);
При вызове функции возвращаемое ею значение можно игнорировать, например:
printf(“OK”);
Тип параметров функции при вызове должен в точности соответствовать типу параметров, указанных при её объявлении.
Помимо определения для функции обычно пишется также её прототип, который
размещается в заголовочном файле с расширением *.h и служит для проверки корректности обращений к функциям при компиляции программы из нескольких модулей.
Прототип функции идентичен заголовку, но заканчивается точкой с запятой, а тело
функции отсутствует:
long double max_ab(long double a, long double b);
Функция в С++ может иметь переменное число параметров. В этом случае за последним обязательным параметром в заголовке функции следует многоточие. Подобной функцией является, например, функция printf().
Следует также отметить, что в С++, в отличие от некоторых других языков программирования нет понятия “вложенных функций”. Все функции в С++ имеют одинаковый ранг.
ПЕРЕГРУЖЕННЫЕ ФУНКЦИИ
Иногда возникает потребность в функциях, выполняющих одни и те же действия
с различными типами данных, например, вычисление максимума из двух чисел и вычисление максимума из двух символов (в смысле алфавитного порядка). Для удобства в
С++ имеется возможность использования перегруженных имён функций, когда функции с одним именем можно идентифицировать по списку параметров, то есть контексту, в котором имя употребляется.
Пример:
long double max_ab(long double a, long double b)
{long double x;
if (a>b) {x=a} else {x=b};
return x;
}
char max_ab(char a, char b)
{char x;
if (a>b) {x=a} else {x=b};
return x;
}
Теперь функцию max_ab можно вызывать как с вещественными параметрами,
так и с параметрами типа char.
Перегруженные функции являются, по сути, различными функциями, идентифицируемыми не только по имени, но и по списку параметров. Отметим, что допусти-
мо перегружать функции, отличающиеся только типом параметров. Если функции отличаются только типом возвращаемого значения, то их перегружать нельзя.
ОБЛАСТЬ ДЕЙСТВИЯ ПЕРЕМЕННЫХ И СВЯЗАННЫЕ С НЕЮ ПОНЯТИЯ
Переменные в С++ могут быть локальными и глобальными, статическими и автоматическими, регистровыми, внешними и нестабильными. Они различаются областью действия, видимостью и временем жизни.
Областью действия переменной называется та часть программы, где переменная
доступна для программного кода. По своей области действия переменные делятся на
локальные и глобальные. Локальные переменные объявляются внутри функции и вне
её не доступны. К ним можно обращаться только в пределах объявляющей их функции.
Если две функции описывают локальную переменную с одним именем, то это две совершенно различные переменные и никакой неоднозначности не возникает. (Параметры в определении функции можно рассматривать в этом смысле как локальные переменные, инициализируемые значениями аргументов при вызове).
В противоположность локальным, глобальные переменные не относятся ни к
какой функции и объявляются совершенно независимо. В пределах текущего модуля
имя глобальной переменной должно быть уникальным. Областью действия глобальных
переменных является (в принципе) вся программа. Если имя локальной переменной
функции совпадает с именем глобальной, то локальная переменная в этом случае скрывает глобальную переменную с тем же именем (говорят ещё, что глобальная переменная становится невидимой внутри тела функции).
Для придания переменным некоторых специфических свойств в С++ существуют следующие модификаторы переменных:
static. Если локальная переменная объявлена в функции как static, то она будет сохранять своё значение между вызовами этой функции (то есть, фактически, существовать
всё время, пока программа выполняется). Если модификатор static применить к глобальной переменной, то он ограничит область её действия текущим модулем компиляции.
auto. Специфицирует переменную как создаваемую автоматически и предполагается
по умолчанию.
register. Рекомендует компилятору разместить локальную переменную в регистре процессора, если это возможно.
extern. Служит указанием компилятору, что переменная является внешней, то есть
объявлена в другом модуле.
volatile. Служит для отметки нестабильных переменных.
Пример:
extern long double pi;
long double circle_square(long double r)
{long double s;
s=pi*r*r;
return s;
}
В данном примере объявлена функция circle_square, вычисляющая площадь круга. Для
вычисления она использует переменную pi, которая объявлена в другом модуле программы.
СОЗДАНИЕ ПРОГРАММЫ ИЗ НЕСКОЛЬКИХ МОДУЛЕЙ
Для создания в среде Turbo C++ Explorer программы из нескольких модулей
следует подключить тексты нужных модулей к проекту. Если модули создаются заново, следует выбрать в главном меню опции File|New|Unit. Если подключается уже созданный модуль, нужно выбрать в главном меню Project|Add to project и указать нужный файл.
Следует также создать для каждого модуля заголовочные файлы *.h, куда помещать прототипы описанных в модулях функций, чтобы сделать их видимыми для других модулей программы с помощью директивы #include”*.h”. (См. также пример программы к лекции 3).
УСЛОВНАЯ КОМПИЛЯЦИЯ КОДА
Я зык С содержит специальные средства, позволяющие производить выборочную компиляцию различных участков кода в зависимости от оценки некоторого константного выражения или определения идентификатора. Для этого служат директивы
#if, #elif, #else, #endif, #ifdef, #ifndef,. Общая форма применения директив компилятора
следующая:
#if выражение_1
оператор_1
#elif выражение_2
оператор_2
#elif выражение_3
оператор_3
#else
оператор_4
#endif
Группа операторов оператор_1 компилируется, если выражение_1 истинно; в
противном случае группа оператор_1 опускается. Группа операторов оператор_2 компилируется, если выражение_1 ложно, и выражение_2 истинно, и т.д. Группа оператор_4 компилируется, если все условные выражения ложны. Конструкция условной
компиляции должна заканчиваться директивой #endif. Разделы #elif и #else могут отсутствовать.
В директивах имеются очень полезные директивы #define и #undef, позволяющие определить и разопределить макроопределение. Они позволяют проверить, определён ли некоторый символ:
#define TEST
….
#ifdef TEST
оператор_1
#else
оператор_2
#endif
В данном примере, если компилятор прошёл по первой строке (#define TEXT),
то он откомпилирует группу операторов оператор_1, а если нет – группу операторов
оператор_2.
Условная компиляция кода применяется на практике для предотвращения включения файлов, переключения разделов кода и выдачи отладочных диагностических сообщений.
Предотвращение включения файлов.
Иногда при использовании заголовочных файлов может происходить дублирование кода из-за повторного включения некоторого файла. Чтобы предотвратить повторное включение кода заголовочного файла можно организовать контроль, поместив
в заголовочный файл следующие строки (первые две – в начало, последнюю – в конец
файла):
#ifndef HEADERO_H
#define HEADERO_H
…
…
#endif
Переключение разделов кода
Директивы условной компиляции могут использоваться для простого переключения между двумя различными вариантами кода – старым и обновленным алгоритмом, например. Это можно сделать так:
#define NEW_VER I
#if NEW_VER
// Экспериментальный код.
#else
// Старый код.
#endif
Отладочные диагностические сообщения
При отладке больших и сложных программ можно с большой пользой применять макросы, генерирующие операторы вывода различных сообщений (например, значений переменных, о начале и завершении функции и т.д.)
#define DEBUG_INFO 1
……
#if DEBUG_INFO
printf(“Function 1 started\n”);
#endif
ЗАДАНИЕ К ЛЕКЦИИ 3
Написать функции, вычисляющие периметр и площадь треугольника по значениям
длин трёх его сторон. Разместить их в отдельном модуле (отличном от того, где располагается функция main( )). Ввести с консоли значения длин сторон треугольника (с
проверкой на корректность неравенства треугольника) и выдать на консоль вычисленные с помощью написанных функций значения его периметра и площади.
Download