246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 22
Текст из файла (страница 22)
Именно науказатель команды ложится ответственность следить за тем, какая строка программы должнавыполнятьсяследующей.Сама программа находится в памяти компьютера, которая специально отведена для того,чтобы хранить операторы программы в двоичном формате. Каждая строка исходного текстапрограммытранслируетсяврядкоманд,акаждаяизэтихкомандхранитсявпамятипосвоемуадресу. Указатель команды содержит адрес следующей команды, предназначенной длявыполнения.Этаидеяиллюстрируетсянарис.5.6.Рис.5.6.УказателькомандыСтек — это специальная область памяти, выделенная для хранения данных вашейпрограммы, требуемых каждой вызываемой функцией. Она называется стеком потому, чтопредставляет собой очередь типа "последним пришел — первым вышел" и напоминает стопкутарелокврукахофицианта(рис.5.7).Принцип"последнимпришел—первымвышел"означает,чтоэлемент,добавленныйвстекпоследним, будет вынут из него первым.
Большинство же очередей функционирует подобноочереди в театр: первый, кто занял очередь, первым из нее и выйдет (и войдет в театр). Стекскорее напоминает стопку монет, удерживаемых специальным приспособлением. Еслирасположить в нем 10 монет достоинством в 1 копейку, а затем попытаться вынуть несколькомонет,топервойвыдостанетету,чтобылавставленапоследней.При помещении данных в стек он расширяется, а при возвращении данных из стека —сужается. Невозможно из стопки достать одну тарелку, не вынув предварительно все тарелки,помещенныевстопкупередней.Тожесправедливодляданныхвстекепамяти.Рис.5.7.СтекАналогия со стопкой тарелок приводится чаще всего.
Такое сравнение довольно наглядно,ноневполневерновсмыслетехникивыполнения.Болееточноепредставлениепозволитсоздатьрядпрямоугольныхполей,выровненныхсверхувниз.Вершинойстекабудетслужитьлюбоеполе,на которое указывает в данный момент указатель вершины стека (эту роль выполняет другойрегистр).Все поля имеют последовательные адреса, и один из этих адресов хранится в регистреуказателя вершины стека. Все, что находится ниже вершины стека, относится к стеку. Все, чтонаходитсявышевершиныстека,игнорируется,какпоказанонарис.5.8.Рис.5.8.УказательвершиныстекаПри помещении некоторого значения в стек оно размещается в поле, расположенном надвершинойстека,послечегоуказательвершиныизменяетсятакимобразом,чтобыуказыватьнановое значение.
При удалении значения из стека в действительности происходит лишьизменение адреса указателя вершины стека таким образом, чтобы он указывал на подлежащийудалениюэлементстека.Принципдействиясхематическипоказаннарис.5.9.Рис.5.9.ПеремещениеуказателявершиныстекаСтекифункцииНиже перечислены действия, происходящие с программой, выполняемой под управлениемDOS,припереходектелуфункции.1. Увеличивается адрес, содержащийся в указателе команды, чтобы указывать наинструкцию, следующую после вызова функции. Затем этот адрес помещается в стек и будетслужитьадресомвозвратапозавершениивыполненияфункции.2.
В стеке резервируется место для возвращаемого функцией значения объявленного вамитипа.Есливсистемесдвухбайтовымицелымидлявозвращаемогозначенияобъявлентипint,токстекудобавляютсяещедвабайта,новэтибайтыничегопоканепомещается.3. В указатель команды загружается адрес вызванной функции, который хранится вотдельной области памяти, отведенной специально для этих целей. Поэтому следующейвыполняемойкомандойбудетпервыйоператорвызваннойфункции.4. Текущая вершина стека помечается и содержится в специальном указателе, именуемомуказателем стека.
Все, что добавляется в стек с этого момента и до тех пор, пока функция незавершится,рассматриваетсякаклокальныеданныеэтойфункции.5.Встекпомещаютсявсеаргументы,передаваемыефункции.6. Выполняется команда, адрес которой находится в данный момент в указателе команды,т.е.перваястрокакодафункции.7.Помереопределениявстекеразмещаютсялокальныепеременныеифункции.Когда функция завершается, возвращаемое значение помещается в область стека,зарезервированную на этапе 2.
Затем из стека удаляется все содержимое вплоть до указателястека, благодаря чему стек очищается от локальных переменных и аргументов, переданныхфункции.Затем из стека извлекаются значение возврата функции, которое присваиваетсяпеременной, вызвавшей функцию, и адрес команды, сохраненный в стеке на этапе 1, которыйприсваивается указателю команд.
Таким образом, программа продолжает свою работу соследующей строки после обращения к функции, владея уже значением, возвращенным изфункции.Некоторыедеталиэтогопроцессаизменяютсяприпереходеоткомпилятораккомпиляторуили от компьютера к компьютеру, но основная идея остается прежней независимо отоперационнойсреды.Вобщемслучаепривызовефункцииадресвозвратаиеепараметрывсегдапомещаютсявстек:Напротяжениижизненногоциклафункциивстекдобавляютсялокальныепеременные.Повозвращенииизфункциивсеониудаляютсяизстека.Наследующихзанятияхрассматриваютсянекоторыеособенностидругихобластейпамяти,которыеиспользуютсядляхраненияглобальныхданныхпрограммы.РезюмеНа этом занятии вы познакомились с функциями.
Функция в действительностипредставляет собой подпрограмму, которой можно передавать параметры и из которой можновозвращатьзначение.КаждыйзапускпрограммыC++начинаетсясвыполненияфункцииmain(),которая,всвоюочередь,можетвызыватьдругиефункции.Функция объявляется с помощью прототипа функции, который описывает возвращаемоезначение, имя функции и типы ее параметров. При желании функцию можно объявитьподставляемой (с помощью ключевого слова inline).
В прототипе функции можно такжеобъявить значения, используемые по умолчанию для одного или нескольких параметровфункции.Определениефункциидолжносоответствоватьпрототипуфункциипотипувозвращаемогозначения, имени и списку параметров. Имена функций могут быть перегружены путемизменения количества или типа параметров. Компилятор находит нужную функцию на основеспискапараметров.Локальные переменные функции и аргументы, передаваемые функции, локальны поотношению к блоку, в котором они объявлены. Параметры, передаваемые как значения,представляют собой копии реальных переменных и не могут влиять на значения этихпеременныхввызывающейфункцииВопросыиответыПочемубынесделатьвсепеременныеглобальными?Когда-то именно так и поступали. Но по мере усложнения программ стало очень труднонаходить в них ошибки, поскольку значения глобальных переменных могли быть измененылюбойизфункций,поэтомусложнобылоопределить,какойименноблокпрограммывиновенвошибке.
Многолетний опыт убедил программистов, что данные должны храниться локально(насколько это возможно) и доступ к изменению данных должен быть определен как можноболееузкимкругом.Когдаследуетиспользоватьвпрототипефункцииключевоесловоinline?Если функция невелика (занимает не более одной-двух строк) и встраивание ее в кодпрограммы по всем местам вызова не увеличит существенно размер этой программы, то,возможно,имеетсмыслобъявитьеекакinline.Почемуизменения,вносимыевтелефункциивпеременные,переданныекакаргументы,неотражаютсяназначенияхэтихпеременныхвосновномкодепрограммы?Аргументыобычнопередаютсявфункциюкакзначения,т.е.аргументвфункцииявляетсяна самом деле копией оригинального значения.
Данная концепция подробно разъяснялась наэтомзанятии.Как поступить, если необходимо, чтобы изменения, внесенные в функции, сохранилисьпослевозвращенияизфункции?Эта проблема рассматривается на занятии 8. Использование указателей не только решаетэту проблему, но также предоставляет способ обойти ограничение на возврат только одногозначенияизфункции.Чтопроизойдет,еслиобъявитьследующиедвефункции:intArea(intwidth,intlength=1);intArea(intsize);Будутлиониперегруженными?Условиеуникальностисписковпараметровсоблюдено,новпервомвариантедляпараметраопределенозначение,используемоепоумолчанию.Эти объявления будут скомпилированы, но, если вызвать функцию Area () с однимпараметром, будет сгенерирована ошибка компиляции, обусловленная неопределенностьюмеждуфункциямиArea(int,int)иArea(int).КоллоквиумВэтомразделепредлагаютсявопросыдлясамоконтроляиукрепленияполученныхзнанийи приводится несколько упражнений, которые помогут закрепить ваши практические навыки.Попытайтесьсамостоятельноответитьнавопросытестаивыполнитьзадания,апотомсверьтеполученные результаты с ответами в приложении Г.
Не приступайте к изучению материаласледующей главы, если для вас остались неясными хотя бы некоторые из вопросов,предложенныхниже.Контрольныевопросы1.Вчемразницамеждуобъявлениемпрототипафункциииопределениемфункции?2. Должны ли имена параметров, указанные в прототипе, определении и вызове функциисоответствоватьдругдругу?3.Еслифункцияневозвращаетзначение,какследуетобъявитьтакую<функцию?4. Если не объявить тип возврата, то какой тип будет принят по умолчанию длявозвращаемогозначения?5.Чтотакоелокальнаяпеременная?6.Чтотакоеобластьвидимости?7.Чтотакоерекурсия?8.Когдаследуетиспользоватьглобальныепеременные?9.Чтотакоеперегрузкафункции?10.Чтотакоеполиморфизм?Упражнения1.ЗапишитепрототипдляфункциисименемPerimeter,котораявозвращаетзначениеranaunsignedlongintипринимаетдвапараметратипаипБгдпейshortint.2.
Запишите определение функции Perimeter согласно объявлению в упражнении 1. Двапринимаемых ею параметра представляют длину и ширину прямоугольника, а функциявозвращаетегопериметр(удвоеннаядлинаплюсудвоеннаяширина).3.Жучки:чтонеправильновэтойфункции?#include<iostream.h>voidmyFunc(unsignedshortintx);intmain(){unsignedshortintx,y;y=myFunc(int);cout<<"x:"<<x<<"y:"<<y<<"\n";}voidmyFunc(unsignedshortintx){return(4-х);}4.Жучки:чтонеправильновэтойфункции?#include<iostrearc.h>intmyFunc(unsignedshortintx);intmain(){unsignedshortintx,у;у=myFunc(x);cout<<"x:"<<x<<"у:"<<у<<"\n";}intmyFunc(unsignedshortintx);{return(4*x);}5.
Напишите функцию, которая принимает два параметра типа unsigned short int ивозвращает результат деления первого параметра на второй. Функция не должна выполнятьоперацию деления, если второе число равно нулю, но в этом случае она должна возвратитьзначение-1.6. Напишите программу, которая запрашивает у пользователя два числа и вызываетфункцию, записанную при выполнении упражнения 5.
Выведите результат или сообщение обошибке,еслифункциявозвратитзначение,равное-1.7. Напишите программу, которая запрашивает число и показатель степени. Напишитерекурсивную функцию, которая возводит число в степень путем многократного умножениячисла на самое себя, т.е. если число равно 2, а показатель степени равен 4, то эта функциядолжнавозвратитьчисло16.День6-й.БазовыеклассыБазовые классы расширяют встроенные средства языка C++, что способствует решениюсложныхпроблем,которыеставитпередпрограммистамиреальнаяжизнь.Сегоднявыузнаете:•Чтопредставляютсобойклассыиобъекты•Какопределитьновыйклассисоздатьобъектыэтогокласса•Чтопредставляютсобойфункции-членыипеременные-члены•ЧтотакоеконструкторикакегоиспользоватьСозданиеновыхтиповВыужепознакомилисьстипамипеременных,включаябеззнаковыецелыеисимволы.Типпеременной несет в себе немало информации.
Например, если объявить переменные Height иWidth как беззнаковые короткие целые (unsigned short int), то каждая из них сможет хранитьцелоечисловдиапазоне0—65535,занимаяприэтомтолькодвабайта.Еслижевыпопытаетесьприсвоить такой переменной значение, отличное от беззнакового целого числа, то получитесообщениеобошибке.Этозначит,чтоспомощьютакойпеременнойвынесможетехранитьсвоеимя,такчтодажеинепытайтесьсделатьэто.Лишь объявив переменные Height и Width беззнаковыми короткими целыми, вы получаетевозможность сложить их или присвоить одной из них значение другой.
Итак, тип переменнойопределяет:•ееразмервпамяти;•типданных,которыеонаможетхранить;•операции,которыемогутвыполнятьсясееучастием.Тип данных является категорией. К нему можно отнести автомобиль, дом, человека,фрукты,геометрическуюфигуруит.п.ВязыкеC++программистможетсоздатьлюбойнужныйему тип, и каждый из этих типов может совмещать свойства и функциональные возможностивстроенныхбазовыхтипов.ЗачемсоздаватьновыйтипПрограммы обычно пишут для решения таких реальных проблем, как отслеживаниеинформацииослужащихилиимитацияработыотопительнойсистемы.Ихотярешатьсложныепроблемы можно с помощью программ, написанных только с использованием однихцелочисленныхзначенийисимволов,решениявыгляделибызначительнопроще,еслибыможнобылосоздаватьуникальныетипыдляразличныхобъектов.Другимисловами,имитациюработыотопительной системы было бы гораздо легче реализовать, если бы можно было создаватьпеременные, представляющие помещения, тепловые датчики, термостаты и бойлеры.