246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 27
Текст из файла (страница 27)
Объявление классаназываетсяегоинтерфейсом,посколькуоносообщаетпользователю,каквзаимодействоватьсклассом. Интерфейс обычно хранится в файле с расширением .hpp, который называетсяфайломзаголовка.Из определения функции компилятор узнает, как она работает. Определение функцииназываетсявыполнениемметодаклассаихранитсявфайлесрасширением.cpp.Подробностивыполнения класса касаются только автора класса. Клиентам же класса, т.е. частямпрограммы,использующимэтоткласс,ненужнознать,каквыполняютсяфункции.ВыполнениесподстановкойМожновыполнятьподстановкуметодовспомощьюключевогословаinlineточнотакже,какэтоделалосьсобычнымифункциями.Дляэтогоключевоесловоinlineнужноразместитьпередтипом возвращаемого значения.
Например, определение подставляемой функции-членаGetWeight()имеетследующийвид:inlineintCat::GetWeight(){returnitsweight;//возвращаетпеременную-членWeight}Можно также поместить определение функции в объявление класса, что автоматическиделаеттакуюфункциюподставляемой:classCat{public:intGetWeight(){returnitsWeight;}//подставляемаяфункцияvoidSetWeight(intaWeight);};Обратите внимание на синтаксис определения функции GetWeight(). Тело подставляемойфункции начинается сразу же после объявления метода класса, причем после круглых скобокнет никакой точки с запятой. Подобно определению обычной функции, определение методаначинается с открывающей фигурной скобки и оканчивается закрывающей фигурной скобкой.Какобычно,пробелызначениянеимеют,итожесамоеопределениеможнозаписатьнесколькоиначе:classCat{public:intGetWeight()const{returnitsWeight;}//подставляемаяфункцияvoidSetWeight(intaWeight);};В листингах 6.6 и 6.7 вновь создается класс Cat, но в данном случае объявление классасодержится в файле CAT.hpp, а выполнение — в файле CAT.cpp.
Кроме того, в листинге 6.7методдоступакданнымклассаиметодMeow()являютсяподставляемыми.Листинг6.6.ОбъявлениеклассаCATвфайлеCAT.hpp1:#include<iostream.h>2:classCat3;{4:public:5:Cat(intinitialAge);6:~Cat();7:intGetAge()const{returnitsAge;)//подставляемаяфункция!8:voidSetAge(intage){itsAge=age;}//подставляемаяфункция!9:voidMeow()const{cout<<"Мяу.\n";}//подставляемаяфункция!10:private:11:intitsAge;12:};Листинг6.7.ВыполнениемассаCatвфайлеCAT.cpp1://Примериспользованияподставляемыхфункций2://ивключенияфайлазаголовка3:4:#include"cat.hpp"//незабудьтевключитьфайлзаголовка!5:6:7:Cat::Cat(intinitialAge)//конструктор8:{9:itsAge=initialAge;10:}11:12:Cat::~Cat()//деструктор,невыполняетникакихдействий13:{14:}15:16://Создаемвиртуальнуюкошку,устанавливаемеевозраст,разрешаем17://еймяукнуть,сообщаемеевозраст,затемснова"мяукаем"иизменяемвозрасткошки.18:intmain()19:{20:CatFrisky(5);21:Frisky.Meow();22:cout<<"Friskyisаcatwhois";23:cout<<Frisky.QetAge()<<"yearsold.\n";24:Frisky.Meow();25:Frisky.SetAge(7);26:cout<<"NowFriskyis";27:cout<<Frisky.GetAge()<<"yearsold.\n";28:return0;29:}Результат:Meow.Friskyisаcatwhois5yearsold.Meow.NowFriskyis7yearsold.Анализ: Программа, представленная в листингах 6.6 и 6.7, аналогична программе излистинга6.4заисключениемтого,чтотриметодаклассаобъявляютсяподставляемыми,асамообъявлениеклассавынесеновфайлзаголовкаCAT.hpp.В строке 7 объявляется функция GetAge() и тут же следует определение ее выполнения.Строки 8 и 9 занимают объявления еще двух встроенных функций, но их определениясодержатсявдругомфайле.В строке 4 листинга 6.7 с помощью команды #include "cat.hpp" в программу включаетсясодержимоефайлаCAT.hpp.Компиляторполучаеткомандусчитатьсодержимоефайлаcat.hppиввестиеговданныйфайл,начинаясостроки5.Возможность встраивания файлов в другие файлы позволяет хранить объявления классовотдельно от их выполнения и использовать тогда, когда в этом возникает необходимость.
ЭтостандартныйприемприсозданиипрограммнаязыкеC++.Обычнообъявленияклассовхранятсявфайлесрасширением.hpp,которыйзатемвключаетсявсоответствующийфайл.cppспомощьюдирективы#include.Встроках18—29вточностиповторяетсятелофункцииmain()излистинга6.4.Цельэтогоповторения — показать, что применение подставляемых вариантов функций не внеслоизмененийвиспользованиеэтихфункций.Классысодержащиедругиеклассывкачестведанных-членовНет ничего необычного в построении сложного класса путем объявления более простыхклассов и последующего включения их в объявление сложного класса.
Например, можнообъявитьклассколеса,классмотора,класскоробкипередачит.д.,азатемобъединитьихвклассавтомобиля. Тем самым объявляются и взаимоотношения между классами. Автомобиль имеетмотор,колесаикоробкупередач.Рассмотрим второй пример. Прямоугольник состоит из линий. Линия определяется двумяточками. Каждая точка определяется координатами x и у. В листинге 6.8 показано объявлениекласса Rectangle, которое содержится в файле RECTANGLE.hpp. Поскольку прямоугольникопределяется четырьмя линиями, соединяющими четыре точки, и каждая точка имееткоординаты на графике, то сначала будет объявлен класс Point для хранения координат x,yкаждойточки.Листинг6.9содержитобъявленияобоихклассов.Листинг6.8.Объявлениеклассовточкиипрямоугольника1://НачалофайлаRect.hpp2:#include<iostream.h>3:classPoint//храниткоординатыx,y4:{5://нетконструктора,используетсяконструкторпоумолчанию6:public:7:voidSetX(intx){itsX=x;>8:voidSetY(intу){itsY=у;}9:intGetX()const<returnitsX;}10:intGetY()const{returnitsY;}11:private:12:intitsX;13:intitsY;14:};//конецобъявленияклассаPoint15:16:17:classRectangle18:{19:public:20:Rectangle(inttop,intleft,intbottom,intright):.;21:~Rectangle(){}22:23:intGetTop()const{returnitsTop;}24:intGetLeft()const{returnitsLeft;}25:intGetBottom()const{returnitsBottom;}26:intGetRight()const{returnitsRight;}27:28:PointGetUpperLeft()const{returnitsUpperLeft;}29:PointGetLowerLeft()const{returnitsLowerLeft;}30:PointGetUpperRight()const{returnitsUpperRight;}31:PointGetLowerRight()const{returnitsLowerRight;}32:33:voidSetUpperLeft(PointLocation){itsUpperLeft=Location;}34:voidSetLowerLeft(PointLocation){itsLowerLeft=Location;}35:voidSetUpperRight(PointLocation){itsUpperRight=Location;}36:voidSetLowerRight(PointLocation){itsLowerRight=Location;}37:38:voidSetTop(inttop){itsTop=top;}39:voidSetLeft(intleft){itsLeft=left;}40:voidSetBottorn(intbottom){itsBottom=bottom;}41:voidSetRight(intright){itsRight=right;}42:43:intGetArea()const;44:45:private:46:PointitsUpperLeft;47:PointitsUpperRight;48:PointitsLowerLeft;49:PointitsLowerRight;50:intitsTop;51:intitsLeft;52:intitsBottom;53:intitsRight;54:};55://конецфайлаRect.hppЛистинг6.9.СодержимоефайлаRECT.cpp1://Началофайлаrect.cpp2:#include"rect.hpp"3:Rectangle::Rectangle(inttop,intleft,intbottom,intright)4:{5:itsTop=top;6:itsLeft=left;7:itsBottom=bottom;8:itsRight=right;9:10:itsUpperLeft.SetX(left);11:itsUpperLeft.SetY(top);12:13:itsUpperRight.SetXtright);14:itsUpperRight.SetY(top);15:16:itsLowerLeft.SetX(left);17:itsLowerLeft.SetY(bottom);18:19:itsLowerRight.SetX(right);20:itsLowerRight.SetY(bottom);21:}22:23:24://Вычисляемплощадьпрямоугольника,отыскиваяегостороны25://определяемегодлинуиширину,азатемперемножаемих26:intRectangle::GetArea()const27:{28:intWidth=itsRignt-itsLeft;29:intHeight=itsTop-itsBottom;30:return(Width>>Height);31:}32:33:intmain()34:{35://инициализируемлокальнуюпеременнуюRectangle36:RectangleMyRectangle(100,20,50,80);37:38:intArea=MyRectangle.GetArea();39:40:cout<<"Area:"<<Area<<"\n";41:cout<<"UpperLeftXCoordinate:";42:cout<<MyRectangle.GetUpperLeft().GetX();43:return0;44:}Результат:Area:3000UpperLeftXCoordinate:20Анализ: В строках 3-14 листинга 6.8 объявляется класс Point, который используется дляхраненияконкретныхкоординатx,yнаграфике.ВданнойпрограммеклассPointпрактическинеиспользуется.Однаковдругихметодахрисованияоннезаменим.Внутри объявления класса Point (в строках 12 и 13) объявляются две переменные- члена(itsXиitsY).Этипеременныехранятзначениякоординатточки.Приувеличениикоординатыxмы перемещаемся на графике вправо.
При увеличении координаты у мы перемещаемся награфике вверх. В других графиках могут использоваться другие системы координат (с другойориентацией). Например, в некоторых программах построения окон значение координаты уувеличиваетсяприперемещениивобластиокнавниз.В классе Point используются подставляемые inline-функции доступа, предназначенные длячтенияиустановкикоординатточекXиY.Этифункцииобъявляютсявстроках7-10.Вобъектахкласса Point используются стандартные конструктор и деструктор, предоставляемыекомпилятором по умолчанию.
Следовательно, координаты точек должны устанавливаться впрограмме.В строке 17 начинается объявление класса Rectangle, который включает четыре точки,представляющиеуглыпрямоугольника.КонструкторклассаRectangleпринимаетчетырецелочисленныхпараметра,именуемыхtop(верхний), left (левый), bottom (нижний) и right (правый). Эти четыре параметра, передаваемыеконструктору, копируются в соответствующие четыре пере- менные-члена (см. листинг 6.9),послечегоустанавливаютсячетыреточки(четыреобъектаклассаPoint).Помимо обычных функций доступа к данным-членам класса, в классе RectangleпредусмотренафункцияGetArea(),объявленнаявстроке43.Вместохранениязначенияплощадив виде переменной эта функция вычисляет площадь в строках 28 и 29 листинга 6.9.
Для этогосначала вычисляются значения длины и ширины прямоугольника, а затем полученныерезультатыперемножаются.ДляполучениякоординатыверхнеголевогоуглапрямоугольниканужнополучитьдоступкточкеUpperLeftизапроситьеезначениеX.ПосколькуфункцияGetUpperLeft()являетсяметодомклассаRectangle,онаможетнепосредственнополучитьдоступкзакрытымданнымэтогокласса,включая и доступ к переменной itsUpperLeft. Поскольку переменная itsUpperLeft являетсяобъектом класса Point, а переменная itsX этого объекта закрытая, функция GetUpperLeft() неможетпрямообратитьсякэтойпеременной.ВместоэтогодляполучениязначенияпеременнойitsXонадолжнаиспользоватьоткрытуюфункциюдоступаGetX().В строке 33 листинга 6.9 начинается тело основной части программы.
До выполнениястроки36никакойпамятиневыделялосьиничего,посути,непроисходило.Все,сделанноедосих пор, служило одной цели — сообщить компилятору, как создается точка и как создаетсяпрямоугольник(наслучай,есливэтомпоявитсянеобходимость).В строке 36 определяется прямоугольник (объект класса Rectangle) путем передачиреальныхзначенийдляпараметровTop,Left,BottomиRight.Встроке37создаетсялокальнаяпеременнаяAreaтипаint.Онапредназначенадляхраненияплощади созданного прямоугольника.