Область видимости и время жизни объектов.
Объявление и определение функций. Вызов функции.
Любая программа на C++ состоит из функций, одна из которых должна иметь имя main (с нее начинается выполнение программы). Функция начинает выполняться в момент вызова. Любая функция должна быть объявлена и определена.
Объявление функции (прототип, заголовок, сигнатура) задает ее имя, тип возвращаемого значения и список передаваемых параметров. Определение функции со держит, кроме объявления, тело функции, представляющее собой последовательность операторов и описаний в фигурных скобках.
Рассмотрим составные части определения:
· С помощью необязательного модификатора класс можно явно задать область видимости функции, используя ключевые слова extern (глобальная видимость во всех модулях программы) и static (видимость только в пределах модуля, в котором определена функция).
· Тип возвращаемого функцией значения может быть любым, кроме массива и функции. Если функция не должна возвращать значение, указывается тип void.
· Список параметров определяет величины, которые требуется передать в функцию при ее вызове. Элементы списка параметров разделяются запятыми.
В определении, в объявлении и при вызове одной и той же функции типы и порядок следования параметров должны совпадать.
Для вызова функции в простейшем случае нужно указать ее имя, за которым в круглых скобках через запятую перечисляются имена передаваемых аргументов. Вызов функции может находиться в любом месте программы, где по синтаксису допустимо выражение того типа, который формирует функция. Если тип возвращаемого функцией значения не void, она может входить в состав выражений или, в частном случае, располагаться в правой части оператора присваивания.
Формальные и фактические параметры. Механизмы их передачи.
Механизм параметров является основным способом обмена информацией между вызываемой и вызывающей функциями. Параметры, перечисленные в заголовке описания функции, называются формальными параметрами, или просто пара метрами, а записанные в операторе вызова функции — фактическими параметрами, или аргументами.
Существует два способа передачи параметров в функцию: по значению и по адресу. При передаче по значению в стек заносятся копии значений аргументов, и опера торы функции работают с этими копиями. Доступа к исходным значениям пара метров у функции нет, а, следовательно, нет и возможности их изменить. При передаче по адресу в стек заносятся копии адресов аргументов, а функция осуществляет доступ к ячейкам памяти по этим адресам и может изменить исходные значения аргументов.
Перезагрузка функций.
Использование не скольких функций с одним и тем же именем, но с различными типами параметров, называется перегрузкой функций. Компилятор определяет, какую именно функцию требуется вызвать, по типу фактических параметров. Этот процесс называется разрешением перегрузки.
Механизм разрешения основан на достаточно сложном наборе правил, смысл которых сводится к тому, чтобы использовать функцию с наиболее подходящими аргументами и выдать сообщение, если такой не найдется.
Если точного соответствия не найдено, выполняются продвижения порядковых типов в соответствии с общими правилами. Далее выполняются стандартные преобразования типов или указателей. Следующим шагом является выполнение преобразований типа, заданных пользователем, а также поиск соответствий за счет переменного числа аргументов функций. Если соответствие на одном и том же этапе может быть получено более чем одним способом, вызов считается неоднозначным и выдается сообщение об ошибке.
Глобальные переменные.
Глобальные переменные видны во всех функциях, где не описаны локальные переменные с теми же именами, поэтому использовать их для передачи данных между функциями очень легко. Тем не менее это не рекомендуется, поскольку затрудняет отладку программы и препятствует помещению функций в библиотеки общего пользования. Нужно стремиться к тому, чтобы функции были максимально независимы, а их интерфейс полностью определялся прототипом функции.
Область видимости и время жизни объектов.
Время жизни переменной может быть глобальным и локальным. Переменная с глобальным временем жизни характеризуется тем, что в течение всего времени выполнения программы с ней ассоциирована ячейка памяти и значение. Переменной с локальным временем жизни выделяется новая ячейка памяти при каждом входе в блок, в котором она определена или объявлена. Время жизни функции всегда глобально.
Область видимости объекта (переменной или функции) определяет, в каких участках программы допустимо использование имени этого объекта.
Область видимости имени начинается в точке объявления, точнее, сразу после объявителя, но перед инициализатором. Поэтому допускается использование имени в качестве инициализирующего значения для себя самого.
Классы памяти.
Класс памяти определяет порядок размещения объекта в памяти. Различают автоматический и статический классы памяти. C++ располагает четырьмя спецификаторами класса памяти:1) auto 2) register 3) static 4) extern
По два для обозначения принадлежности к автоматическому и статическому классам памяти.
В свою очередь, статический класс памяти может быть локальным (внутренним) или глобальным (внешним).
Спецификаторы позволяют определить класс памяти определяемого объекта:
· auto. Этот спецификатор автоматического класса памяти указывает на то, что объект располагается в локальной (или автоматически распределяемой) памяти. Объекты, имена которых объявляются со спецификатором auto, размещаются в локальной памяти непосредственно перед началом выполнения функции или блока операторов.
· register. Ещё один спецификатор автоматического класса памяти. Применяется к объектам, по умолчанию располагаемым в локальной памяти. Представляет из себя "ненавязчивую просьбу" к транслятору (если это возможно) о размещении значений объектов, объявленных со спецификатором register в одном из доступных регистров, а не в локальной памяти
· static. Спецификатор внутреннего статического класса памяти. Применяется только(!) к именам объектов и функций. В C++ этот спецификатор имеет два значения. Первое означает, что определяемый объект располагается по фиксированному адресу. Тем самым обеспечивается существование объекта с момента его определения до конца выполнения программы. Второе значение означает локальность.
· extern. Спецификатор внешнего статического класса памяти. Обеспечивает существование объекта с момента его определения до конца выполнения программы. Объект, объявленный со спецификатором extern доступен во всех модулях программы, то есть глобален.
Выбор класса памяти, помимо явных спецификаторов, зависит от размещения определения или объявления в тексте программы. Модуль, функция, блок могут включать соответствующие операторы объявления или определения, причём всякий раз определяемый объект будет размещаться в строго определённых областях памяти.
Рекурсивные функции.
Рекурсивной называется функция, которая вызывает саму себя. Такая рекурсия называется прямой. Существует еще косвенная рекурсия, когда две или более функций вызывают друг друга. Если функция вызывает себя, в стеке создается копия значений ее параметров, как и при вызове обычной функции, после чего управление передается первому исполняемому оператору функции. При повтор ном вызове этот процесс повторяется. Ясно, что для завершения вычислений каждая рекурсивная функция должна содержать хотя бы одну нерекурсивную ветвь алгоритма, заканчивающуюся оператором возврата. При завершении функции соответствующая часть стека освобождается, и управление передается вызывающей функции, выполнение которой продолжается с точки, следующей за ре курсивным вызовом.
Рекурсивные функции чаще всего применяют для компактной реализации ре курсивных алгоритмов, а также для работы со структурами данных, описанными рекурсивно, например, с двоичными деревьями. Любую рекурсивную функцию можно реализовать без применения рекурсии, для этого программист должен обеспечить хранение всех необходимых данных самостоятельно. Достоинством рекурсии является компактная запись, а недостатками — расход времени и памяти на повторные вызовы функции и передачу ей копий параметров, и, главное, опасность переполнения стека.
Подробное изложение теоретических вопросов, затронутых в первой лекции, можно найти в литературе [1, 3]. Практические аспекты этих вопросов можно отыскать в работах [2, 4,5,6,7,8].
Список рекомендуемой литературы
а) основная литература:
1. Павловская Т.А. С/C++: Программирование га языке высокого уровня. Учебник. – СПб.: Питер,2001.
2. Шумова Е.О. Программирование на языке высокого уровня: Учеб. Пособие. – СПб.:СЗТУ, 2001.
3. Макаров В.Л. Программирование и основы алгоритмизации: Учеб. Пособие. – СПб.:СЗТУ, 2003.
б) дополнительная литература:
4. Березин Б.И., Березин С.Б. Начальный курс С и С++. - : Диалог – Мифи, 1997.
5. Джесс Либерти. Освой самостоятельно С++ за 21 день. - М.: Издательский дом «Вильямс», 2001.
6. Неформальное виденье в С++ и Turbo Vision. – Галерея «Петрополь», 1992.
7. Петухова Н.М. Вычислительная техника и программирование. Конспект лекций. – Л.: СЗПИ, 1991.
в) прочая литература:
8. http://www.tdoc.ru/c/programming/cpp/cpp-velvet-way-page23.html
9. http://citforum.ru/programming/cpp_march/cpp_022.shtml
10. http://mycpp.ru/cpp/book/c08.html
Знания следует самостоятельно проверить путем ответов на контрольные вопросы:
1. В чем разница между объявлением прототипа и определением функции?
2. Должны ли имена параметров, указанные в определение и вызове функции, соответствовать друг другу?
3. Как следует объявлять функцию, если она не возвращает значения?
4. Что такое локальная переменная?
5. Что такое глобальная переменная?
6. Что такое область видимости?
7. Что такое перегрузка функции?
8. Что такое рекурсия?
9. Когда следует использовать глобальные переменные?
10. К какому классу памяти будет относиться переменная по умолчанию?