246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 25
Текст из файла (страница 25)
Благодаря этому-синтаксису компилятор узнает, чтоопределяемая здесь функция GetAge() — это функция, объявленная в классе Cat. Заисключениемстрокизаголовка,GetAge()создаетсяточнотакже,какидругиефункции.ОпределениефункцииGetAge()занимаеттолькооднустроку,вкоторойуказывается,чтоэтафункциявозвращаетзначениепеременной-членаitsAge.Обратитевнимание,чтофункцияmain()не может получить доступ к этой переменной, поскольку она объявлена в закрытом разделекласса Cat. При этом из функции main() можно обратиться к открытому методу GetAge(). АпосколькуметодGetAge()являетсяфункцией-членомклассаCat,тоонимеетвсеправадоступак переменной-члену itsAge. В результате функция GetAge() возвращает значение переменнойitsAgeвфункциюmain().В строке 26 начинается определение функции-члена SetAge().
Она принимаетцелочисленный параметр и присваивает переменной itsAge значение этого параметра (строка30). Являясь членом класса Cat, функция SetAge() имеет прямой доступ к переменной-членуitsAge.Встроке37начинаетсяопределениеметодаMeow()классаCat.Этотметодзанимаетвсегооднустроку,вкоторойвыводитсянаэкрансловоMeow,азатемвыполняетсяпереходнановуюстроку.Помните,чтодляпереходанановуюстрокуиспользуетсясимвол\n.В строке 44 начинается тело функции main(); она не принимает никаких аргументов. Встроке 46 в функции main() объявляется объект класса Cat с именем Frisky. В строке 47переменной-члену itsAge присваивается значение 5 с помощью метода доступа SetAge().Обратите внимание, что в вызове этого метода указывается имя объекта (Frisky), за которымследуетоператорпрямогодоступа(.),иимясамогометода(SetAge()).Такимспособомможновызыватьлюбыедругиеметодыкласса.Встроке48вызываетсяфункция-членMeow(),австроке49наэкранвыводитсязначениепеременной-члена с использованием функции доступа GetAge().
В строке 51 функция Meow()вызываетсяснова.КонструкторыидеструкторыСуществует два способа определения целочисленной переменной. Во-первых, можноопределить переменную, а затем (несколько ниже в программе) присвоить ей некотороезначение,например:intWeight;//определяемпеременную//здесьследуютдругиевыраженияWeight=7;//присваиваемзначениепеременнойМожнотакжеопределитьпеременнуюинемедленноееинициализировать,например:intWeight=7;//определяемиинициализируемзначением7.Операция инициализации сочетает в себе определение пербмбнной с присвоениемначального значения. Причем ничто не может помешать вам впоследствии изменить этозначение.Крометого,инициализация,проведеннаяодновременносопределением,гарантирует,что переменная не будет содержать мусор, оставшийся в выделенных переменной ячейкахпамяти.Как же инициализировать переменные-члены класса? Для этого в классе используетсяспециальнаяфункция-член,называемаяконструктором.Принеобходимостиконструкторможетпринимать параметры, но не может возвращать значения даже типа void.
Конструктор — этометодкласса,имякоторогосовпадаетсименемсамогокласса.Объявив конструктор, вам также стоит объявить и деструктор. Если конструкторы служатдля создания и инициализации объектов класса, то деструкторы удаляют из памятиотработавшие объекты и освобождают выделенную для них память. Деструктору всегдаприсваиваетсяимяклассассимволомтильды(~)вначале.Деструкторынепринимаютникакихаргументов и не возвращают никаких значений. Объявление деструктора класса Cat будетвыглядетьследующимобразом:~Cat();Конструкторыидеструкторы,заданныепоумолчаниюЕсли вы не объявите конструктор или деструктор, то компилятор сделает это за вас.Стандартные конструктор и деструктор не принимают аргументов и не выполняют никакихдействий.Вопросыиответы:Конструкторназываетсястандартнымиз-заотсутствияаргументовилииз-за того, что создается компилятором в том случае, если в классе не объявляется никакойдругойконструктор?Стандартный конструктор, или конструктор по умолчанию, характеризуется тем, что непринимает никаких аргументов, причем неважно, создан ли этот конструктор автоматическикомпилятором или самим программистом.
Стандартный конструктор всегда используется поумолчанию.Однако что касается деструкторов, то тут есть свои отличия. Стандартный деструкторпредоставляется компилятором. Поскольку все деструкторы не имеют параметров, то главнойотличительной чертой стандартного деструктора является то, что он не выполняет никакихдействий,т.е.имеетпустоетелофункции.Использованиеконструктора,заданногопоумолчаниюКакая же польза от конструктора, который ничего не выполняет? Зачастую это нужнотолько для протокола. Все объекты должны быть локализованы в программе, поэтому ихсоздание и удаление сопровождается вызовом соответствующей функции, которая при этомможетничегоинеделать.Так,дляобъявленияобъектабезпередачипараметров,например:CatRags;//Ragsнеполучаетникакихпараметровнеобходимоиметьследующийконструктор:Cat();Конструктор вызывается при определении объекта класса.
Если для создания объектаклассаCatследуетпередатьдвапараметра,токонструкторклассаCatопределяетсяследующимобразом:CatFrisky(5,7);Есликонструкторпринимаетодинпараметр,определениеобъектабудетиметьследующийвид:CatFrisky(3);Вслучае,когдаконструкторвообщенепринимаетпараметров(т.е.являетсястандартным),отпадаетнеобходимостьиспользованиякруглыхскобок:CatFrisky;Этот случай является исключением из правила, гласящего, что все функции требуютналичия круглых скобок, даже если они вовсе не принимают параметров.
Вот почему можноспокойнозаписатьтакоеопределение:CatFrisky;Эта запись интерпретируется как обращение к стандартному конструктору. В нейотсутствуетпередачапараметрови,какследствие,круглыескобки.Обратитевнимание,чтовынеобязаныпостоянноиспользоватьстандартныйконструктор,предоставляемый компилятором. Всегда можно написать собственный стандартныйконструктор, т.е. конструктор без параметров. Вы вольны наделить свой стандартныйконструктортеломфункции,вкоторомбудетвыполнятьсяинициализациякласса.Чтобы придать законченность своему труду, при объявлении конструктора не забудьтеобъявитьидеструктор,дажеесливашемудеструкторунечегоделать.Ихотясправедливото,чтои стандартный конструктор будет корректно работать, отнюдь не повредит объявитьсобственныйдеструктор.Этосделаетвашупрограммуболееясной.В листинге 6.4 в знакомый уже вам класс Cat добавлены конструктор и деструктор.Конструктор используется для инициализации объекта Cat и установки его возраста равнымпредоставляемому вами значению.
Обратите внимание на то, в каком месте программывызываетсядеструктор.Листинг6.4.Использованиеконструкторовидеструкторов.1://Примеробъявленияконструктораи2://деструкторавклассеCat3:4:#include<iostream.h>//дляобъектаcout5:6:classCat//началообъявлениякласса7:{8:public://началооткрытогораздела9:Cat(intinitialAge);//конструктор10:~Cat();//деструктор11:intGetAge();//методдоступа12:voidSetAge(intage);//методдоступа13:voidMeow();14:private://началозакрытогораздела15:intitsAge;//переменная-член16:};17:18://конструкторклассаCat19:Cat::Cat(intinitialAge)20:{21:itsAge=initialAge;22:}23:24:Cat::~Cat()//деструктор,невыполняющийдействий25:{26:}27:28://GetAge,открытаяфункцияобеспечениядоступа,29://возвращаетзначениепеременной-членаitsAge30:intCat::GetAge()31:{32:returnitsAge;33:}34:35://ОпределениеSetAge,открытой36://функцииобеспечениядоступа37:38:voidCat::SetAge(intage)39:{40://устанавливаемпеременную-членitsAgeравной41://значению,переданномупараметромage42:itsAge=age;43:}44:45://ОпределениеметодаMeow46://возвращаетvoid47://параметровнет48://используетсядлявыводанаэкрантекста"Meow"49:voidCat::Meow()50:{51:cout<<"Meow.\n";52:}53:54://Создаемвиртуальнуюкошку,устанавливаемеевозраст,разрешаем55://еймяукнуть,сообщаемеевозраст,затемснова"мяукаем"иизменяемвозрасткошки.56:intmain()57:{58:CatFrisky(5);59:Frisky.Meow();60:cout<<"Friskyisаcatwhois";61:cout<<Frisky.QetAge()<<"yearsold.\n";62:Frisky.Meow();63:Frisky.SetAge(7);64;cout<<"NowFriskyis";65:cout<<Frisky.GeMje()<<"yearsold.\n";66:return0;67:}Результат:Meow.Friskyisacatwhois5yearsold.Meow.NowFriskyis7yearsold.Анализ:Листинг6.4подобенлистингуб.Ззаисключениемтого,чтовстроке9добавляетсяконструктор, который принимает в качестве параметра целочисленное значение.
В строке 10объявляетсядеструктор,которыйнепринимаетникакихпараметров.Помните,чтодеструкторыникогда не принимают параметров; кроме того, ни конструкторы, ни деструкторы невозвращаютникакихзначений—дажезначениятипаvoid.В строках 19—22 определяется выполнение конструктора, аналогичное выполнениюфункциидоступаSetAge(),котораятакженевозвращаетникакогозначения.В строках 24—26 определяется деструктор ~Cat(). Эта функция не выполняет никакихдействий,нокольвыобъявляетееевклассе,нужнообязательновключитьиееопределение.В строке 58 содержится определение объекта класса Cat с именем Frisky. В конструкторобъекта Frisky передается значение 5. В данном случае нет никакой необходимости вызыватьфункцию-член SetAge(), поскольку объект Frisky создавался с использованием значения 5,присвоенного переменной-члену itsAge, как показано в строке 61.
В строке 63 переменнойitsAgeобъектаFriskyприсваиваетсязначение7,наэтотразспомощьюфункцииSetAge().Новоезначениевыводитсянаэкранвстроке65.Рекомендуется:Используйтеконструкторыдляинициализацииобъектов.Heрекомендуется:Непытайтесьспомощьюконструктораилидеструкторавозвращатькакоебытонибылозначение.Непередавайтедеструкторампараметры.Объявлениефункций-членовсоспецификаторомconstВязыкеC++предусмотренавозможностьобъявитьметодклассатакимобразом,чтотакомуметодубудетзапрещеноизменятьзначенияпеременных-членовкласса.Дляэтоговобъявлениифункции используется ключевое слово const, стоящее после круглых скобок, но перед точкой сзапятой. Например, объявим таким образом функцию-член SomeFunction(), которая непринимаетаргументовивозвращаетзначениетипаvoid:voidSomeFunction()const;Функциидоступакданнымчастообъявляютсясоспецификаторомconst.ВклассеCatестьдвефункциидоступа:voidSetAge(intanAge);intGetAge();Функция SetAge() не может быть объявлена со спецификатором const, поскольку онаизменяет значение переменной-члена itsAge.
А в объявлении функЦии.^Аде() может и дажедолжениспользоватьсяспецификаторconst,посколькуонанедолжнаничегоизменятьвклассе.Функция GetAge() просто возвращает текущее значение переменной-члена itsAge.Следовательно,объявлениеэтихфункцийнеобходимозаписатьвтакомвиде:voidSetAge(intanAge);intGetAge()const;Если некоторая функция объявлена с использованием спецификатора const, а в еевыполнении происходит изменение какого-либо члена объекта, то компилятор покажетсообщение об ошибке. Например, если записать функцию GetAge() таким образом, чтобы онаподсчитывала, сколько раз запрашивался возраст объекта Cat, будет обязательно сгенерированаошибка компиляции, поскольку при таком подсчете (т.е.