Vvmebel.com

Новости с мира ПК
1 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Программирование классы и методы

Программирование на C, C# и Java

Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы

ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode

Что такое класс в ООП

Класс – это ключевое понятие в объектно-ориентированном программировании. Не до конца понимая, что такое класс, невозможно успешно программировать в рамках парадигмы ООП. Данная статья посвящена понятию класса и его базовым элементам, таким как поля, методы и конструкторы.

Когда Вы переходите от процедурных языков (Си, Pascal, Basic) к объектно-ориентированным (C#, Java, C++), первое, что вам нужно сделать – это сломать своё мышление относительно того, что программирование – это написание функций и их последовательный вызов в некоторой главной (main). В рамках ООП вам придётся мыслить более абстрактно и работать с классами, которые являются воплощением объектов реального мира. Казалось бы, почему мыслить в рамках реальных объектов – это значит мыслить более абстрактно?

В программировании, которое изначально было процедурным, переход в объектам – это переход на один уровень абстракции выше. Парадоксально, но новичкам на первых порах довольно сложно перейти к мышлению в рамках реальных объектов при написании кода. Но освоив объектно-ориентированное программирование, вы, несомненно, останетесь довольны, потому что его мощь позволит вам создавать сложные программы значительно быстрее. Мы же со своей стороны постараемся на примерах доходчиво объяснить, что такое класс, и как его использовать. Приступим.

Что такое класс?

В объектно-ориентированном программировании (ООП) – класс это основной элемент, в рамках которого осуществляется конструирование программ. Класс содержит в себе данные и код, который управляет этими данными.

Класс зачастую описывает объект реального мира. Как и реальный объект, класс содержит свой набор параметров и характеристик. Каждый такой параметр называется поле класса (очень похоже на обычные переменные). Также класс способен манипулировать своими характеристиками (полями) с помощью методов класса (похожи на функции в процедурных языках). Рассмотрим такой объект, как автомобиль.

Оговоримся, что данная статья исключительно для начинающих. В ней не рассматривается наследование, абстрактные классы и т.д.

Создание класса

Что имеет автомобиль? В частности, это:

  • марка;
  • цвет;
  • мощность (в л/с);
  • максимальная скорость (км/ч);
  • объём бака (л);
  • расход топлива (л) на 100 км пути.

Напишем класс Car (автомобиль) на C# (аналогично на Java):

Что такое классы в объектно-ориентированном программировании

В этом цик­ле ста­тей мы гово­рим об объектно-ориентированном про­грам­ми­ро­ва­нии — пере­до­вом и очень рас­про­стра­нён­ном под­хо­де к раз­ра­бот­ке. Это сто­ит знать всем, кто серьёз­но отно­сит­ся к про­грам­ми­ро­ва­нию и хочет зара­ба­ты­вать в этой обла­сти.

Если не чита­ли преды­ду­щую ста­тью, вот крат­кое содер­жа­ние:

  • ООП — это под­ход к про­грам­ми­ро­ва­нию. Такой набор прак­тик и прин­ци­пов, кото­ры­ми поль­зу­ют­ся хоро­шие раз­ра­бот­чи­ки. Про­ти­во­по­став­ле­ние это­му под­хо­ду — тра­ди­ци­он­ное про­це­дур­ное про­грам­ми­ро­ва­ние.
  • В про­це­дур­ном про­грам­ми­ро­ва­нии мы пишем функ­ции, кото­рые выпол­ня­ют какие-то зада­чи. И при необ­хо­ди­мо­сти вызы­ва­ем одни функ­ции из дру­гих. В про­грам­ме функ­ции живут отдель­но, дан­ные — отдель­но.
  • Глав­ная про­бле­ма про­це­дур­но­го про­грам­ми­ро­ва­ния — слож­но писать и под­дер­жи­вать боль­шие про­ек­ты. Любой мало-мальски слож­ный про­дукт будет тре­бо­вать сотен функ­ций, кото­рые будут свя­за­ны меж­ду собой. Полу­чит­ся «спагетти-код».
  • В ООП функ­ции и дан­ные груп­пи­ру­ют­ся в объ­ек­ты. Объ­ек­ты более-менее неза­ви­си­мые и обща­ют­ся друг с дру­гом по стро­го опре­де­лён­ным пра­ви­лам.
  • Дан­ные в ООП хра­нят­ся внут­ри объ­ек­тов и назы­ва­ют­ся свой­ства­ми объ­ек­тов. Напри­мер, у объ­ек­та user может быть свой­ство name со зна­че­ни­ем ‘Иван’.
  • Функ­ции в ООП тоже хра­нят­ся внут­ри объ­ек­тов и назы­ва­ют­ся мето­да­ми объ­ек­тов. Напри­мер, у объ­ек­та user может быть метод sendEmail(), кото­рый отправ­ля­ет это­му юзе­ру пись­мо.
  • Мож­но пред­ста­вить, что в ООП взя­ли «спагетти-код» с теф­те­ля­ми и раз­ло­жи­ли из огром­но­го чана пор­ци­он­но по кон­тей­не­рам. Теперь в каж­дом кон­тей­не­ре есть спа­гет­ти и теф­те­ли, и каж­дый про­грам­мист может рабо­тать над сво­им контейнером-объектом, а не ковы­рять­ся в общем чане со спа­гет­ти.

Одно из пре­иму­ществ ООП — не нуж­но мно­го раз писать один и тот же код. Мож­но одна­жды при­ду­мать какую-то кра­си­вую шту­ку и потом зано­во её исполь­зо­вать бук­валь­но одной стро­кой. Для это­го и нуж­ны клас­сы.

Что за классы

Вот одно из фор­маль­ных опре­де­ле­ний клас­са: «Класс — это эле­мент ПО, опи­сы­ва­ю­щий абстракт­ный тип дан­ных и его частич­ную или пол­ную реа­ли­за­цию»

Если более по-русски, то класс — это шаб­лон кода, по кото­ро­му созда­ёт­ся какой-то объ­ект. Это как рецепт при­го­тов­ле­ния блю­да или инструк­ция по сбор­ке мебе­ли: сам по себе класс ниче­го не дела­ет, но с его помо­щью мож­но создать новый объ­ект и уже его исполь­зо­вать в рабо­те.

Если пока непо­нят­но, погру­жай­тесь в при­мер:

При­зо­вём на помощь силу при­ме­ров и пого­во­рим про сото­вые теле­фо­ны.

Допу­стим, вы дела­е­те мобиль­ни­ки и хоти­те выпу­стить на рынок новую модель. Что­бы люди мог­ли сра­зу поль­зо­вать­ся вашим устрой­ством и быст­ро к нему при­вык­ли, у теле­фо­на дол­жен быть экран, кноп­ки вклю­че­ния и гром­ко­сти, каме­ры спе­ре­ди и сза­ди, разъ­ём для заряд­ки и слот для сим-карты.

Но одно­го желе­за недо­ста­точ­но — нуж­но соеди­нить его меж­ду собой так, что­бы всё рабо­та­ло без сбо­ёв. Кро­ме это­го, нуж­но преду­смот­реть, что про­ис­хо­дит при нажа­тии на кноп­ки, что выво­дит­ся на экран и как поль­зо­ва­тель будет управ­лять этим теле­фо­ном.

Сле­ду­ю­щий этап — опи­сать каж­дую деталь, из кото­рой состо­ит теле­фон, каж­дую мик­ро­схе­му и пла­ту, и объ­яс­нить, как дета­ли рабо­та­ют друг с дру­гом. Послед­ний шаг — напи­сать руко­вод­ство поль­зо­ва­те­ля, где будет пол­но­стью рас­ска­за­но, что мож­но делать с теле­фо­ном, как запу­стить зво­нил­ку или отпра­вить смс.

Мы толь­ко что сде­ла­ли новый класс для теле­фо­на — пол­ный набор нуж­ных зна­ний, опи­са­ний, свойств и инструк­ций, кото­рый опи­сы­ва­ет нашу модель. Все эти инструк­ции и опи­са­ния — это ещё не теле­фон, но из них этот теле­фон мож­но сде­лать.

В про­грам­ми­ро­ва­нии у клас­са есть набо­ры дан­ных — в нашем слу­чае это ком­плек­ту­ю­щие для теле­фо­на. Ещё есть функ­ции для рабо­ты с клас­са­ми, кото­рые назы­ва­ют­ся мето­да­ми — это то, как поль­зо­ва­тель будет рабо­тать с нашим теле­фо­ном, что он будет на нём делать и каким обра­зом.

Классы на практике

Все при­ме­ры даль­ше мы будем делать на Python, пото­му что это стиль­но, мод­но и моло­дёж­но. А сам Python — очень объектно-ориентированный язык, почти всё в нём — это объ­ек­ты. Вот и опро­бу­ем.

Допу­стим, мы пишем интернет-магазин с систе­мой ски­док. Нам нуж­но рабо­тать с поль­зо­ва­те­ля­ми — посто­ян­ны­ми поку­па­те­ля­ми. Поль­зо­ва­тель у нас будет объ­ек­том: у него будет имя, воз­раст и адрес достав­ки по умол­ча­нию. Мы заве­дём класс, кото­рый помо­жет нам ини­ци­и­ро­вать ново­го поку­па­те­ля.

Здесь ска­за­но: «Вот класс для поку­па­те­ля. У него есть три свой­ства: имя, воз­раст и адрес». Теперь мы можем заво­дить новых поку­па­те­лей одной стро­кой:

# Созда­ём пер­во­го поку­па­те­ля

# Созда­ём вто­ро­го поку­па­те­ля

Что дальше

В сле­ду­ю­щем мате­ри­а­ле мы смо­де­ли­ру­ем реаль­ную ситу­а­цию: доба­вим про­грам­му лояль­но­сти, бонус­ные бал­лы и рас­ска­жем, как Python с этим спра­вит­ся. Что­бы было инте­рес­нее, будем писать код на двух язы­ках сра­зу — Python и JavaScript.

Классы и объекты

В данном уроке мы рассмотрим классы в C++ и познакомимся с объектно-ориентированным программированием. Объектно-ориентированное программирование или ООП — это одна из парадигм программирования. Парадигма — это, другими словами, стиль. Парадигма определяет какие средства используются при написании программы. В ООП используются классы и объекты. Все наши предыдущие программы имели элементы разных парадигм: императивной, процедурной, структурной.

Читать еще:  Сигнатура в программировании

Мы можем написать одинаковую программу в разных парадигмах. Парадигмы не имеют чёткого определения и часто пересекаются.

Давайте посмотрим на пример. Допустим, в нашей игре есть танки и они могут стрелять, при стрельбе у них уменьшается боезапас. Как мы можем это смоделировать без ООП:

У нас есть структура, которая содержит поле, представляющее количество снарядов, и есть функция атаки, в которую мы передаём танк. Внутри функции мы меняем количество снарядов. Так может выглядеть игра на языке C: структуры отдельно от функций, которые совершают действия со структурными переменными. Данную ситуацию можно смоделировать по-другому с помощью объектно-ориентированного программирования (Object-Oriented Programming, OOP) — ООП.В ООП действия привязываются к объектам.

Определение классов в C++

Класс — это пользовательский тип данных (также как и структуры). Т.е. тип данных, который вы создаёте сами. Для этого вы пишете определение класса. Определение класса состоит из заголовка и тела. В заголовке ставится ключевое слов class, затем имя класса (стандартный идентификатор C++). Тело помещается в фигурные скобки. В C++ классы и структуры почти идентичны. В языке C в структурах можно хранить только данные, но в C++ в них можно добавить действия.

В C++ ключевые слова struct и class очень близки и могут использоваться взаимозаменяемо. У них есть только одно отличие (об этом ниже). Вот как можно определить такой же класс с помощью struct:

Отличие только первом ключевом слове. В одном из прошлых уроков мы уже обсуждали структуры. что мы видим новое? Ключевые слова private и public — это спецификаторы доступа. Также мы видим, что внутри класса мы можем вставлять определения функций.

Определение класса это чертёж. Оно говорит нам из каких данных состоит класс и какие действия он может совершать. т.е. происходит объединение данных и действий в одной сущности.

Переменные и методы класса

Класс состоит из членов класса (class members). Члены класса могут быть переменными (data members) или методами (function members или methods). Переменные класса могут иметь любой тип данных (включая другие структуры и классы). Методы — это действия, которые может выполнять класс. По сути, это обычные функции.

Все методы класса имеют доступ к переменным класса. Обратите внимание, как мы обращаемся к ammo в методе Attack.

Создание объектов класса

Теперь у нас есть свой тип данных и мы можем создавать переменные данного типа. Если после определения структур мы могли создавать структурные переменные, то в случае классов, мы создаём объекты классов (или экземпляры). Разница между классами и структурами только в терминах. Для C++ это почти одно и то же.

Вот так мы можем создать объекты класса Tank и вызвать метод Attack:

t1 и t2 — объекты класса Tank. Для C++ объект класса — это всего-лишь переменная. Тип данных этих переменных — Tank. Ещё раз повторю, что классы (и структуры) позволяют создавать пользовательские типы данных.

В англоязычной литературе создание объектов классов также называется созданием экземпляров — instantiating.

Мы обращаемся к переменным класса и методам с помощью оператора точки (прямой доступ), также как мы обращались к полям структурных переменных.

В нашем примере каждый объект имеет доступ к своей копии ammo. ammo — переменная класса (data member). Attack — метод класса. У каждого объекта своя копия переменных класса, но все объекты одного класса вызывают одни и те же методы.

Размер объекта включает все данные, но не методы

В памяти переменные класса располагаются последовательно. Благодаря этому мы можем создавать массивы объектов и копировать их все вместе (если в классе этих объектов нет динамического выделения памяти). Это будет важно для нас, когда мы начнём работать с графикой в DirectX/OpenGL. Размер объекта класса можно узнать с помощью функции sizeof. При этом в качестве аргумента можно использовать как объект, так и сам класс:

Методы — это все лишь функции. Но в отличии от простых функций, у всех методов есть один скрытый параметр — указатель на объект, который вызывает данный метод. Именно благодаря этому указателю метод знает, какой объект вызвал его и какому объекту принадлежат переменные класса. Внутри метода имя этого указателя — this.

Указатель this

Вот как для компилятора выглядит любой метод:

Это просто иллюстрация. В реальности не нужно указывать аргумент (всё что в круглых скобках). Мы автоматически получаем доступ к указателю this. В данном случае его использование перед ammo необязательно, компилятор автоматически привяжет эту переменную к this.

Указатель this нужен, когда методу необходимо вернуть указатель на текущий объект.

Указатели на объекты

При работе с объектам в C++ вам неизбежно придётся работать с указателями (и ссылками). Как мы помним, при передаче в функцию по значению создаётся копия переменной. Если у вас сложный класс, содержащий большой массив или указатели, то копирование такого объекта может потребовать ненужное выделение дополнительной памяти или может быть вообще невозможным, в случае если в классе вы динамически выделяете память. Поэтому очень часто объекты создаются динамически. Для доступа к таким объектам используется оператор непрямого доступа (стрелочка):

При использовании ссылки на объект, для доступа к его членам используется оператор прямого доступа (точка), т.е. с ссылкой можно обращаться как с обычным объектом:

Чуть ниже мы увидим один случай, когда не обойтись без ссылок.

Конструктор класса (Constructor)

Конструктор класса — метод, вызываемый автоматически при создании объекта. Он используется для инициализации переменных класса и выделении памяти, если это нужно. По сути это обычный метод. Имя обязательно должно совпадать с именем класса и он не имеет возвращаемого значения. Рассмотрим новый класс:

Здесь, в конструкторе задаются начальные значения переменных, но мы можем делать в нём всё что угодно, это обычная функция.

Перегрузка конструктора класса

Перегрузка (overloading) конструктора позволяет создать несколько конструкторов для одного класса с разными параметрами. Всё то же самое, что и при перегрузке функций:

Начальные значения можно задавать в виде списка инициализации. Выше в конструкторе мы инициализировали переменные внутри тела. Список инициализации идёт перед телом конструктора и выглядит так:

В списке инициализации можно задать значение только части переменных класса.

Копирующий конструктор (Copy Constructor)

Без каких-либо действий с нашей стороны мы можем присваивать объектам другие объекты:

Здесь используется копирующий конструктор. Копирующий конструктор по умолчанию просто копирует все переменные класса в другой объект. Если в классе используется динамическое выделение памяти, то копирующий конструктор по умолчанию не сможет правильно создать новый объект. В таком случае вы можете перегрузить копирующий конструктор:

В копирующем конструкторе всегда используются ссылки. Это обязательно. Параметр point — это объект, стоящий справа от оператора присваивания.

Деструктор класса

Деструктор класса — метод, вызываемый автоматически при уничтожении объекта. Это происходит, например, когда область видимости объекта заканчивается. Деструктор нужно писать явно, если в классе происходит выделение памяти. Соответственно, в деструкторе вам необходимо освободить все указатели.

Допустим в нашем танке есть экипаж, пусть это будет один объект типа Unit. При создании танка мы выделяем память под экипаж. В деструкторе нам нужно будет освободить память:

Имя деструктора совпадает с именем класса и перед ним ставится тильда

. Деструктор может быть только один.

Читать еще:  Класс в программировании

Объектно-ориентированное программирование в C++ (ООП)

Теперь, когда мы представляем что такое классы и объекты, и умеем с ними работать, можно поговорить о объектно-ориентированном программировании. Сам по себе стиль ООП предполагает использование классов и объектов. Но помимо этого, у ООП есть ещё три характерные черты: инкапсуляция данных, наследование и полиморфизм.

Инкапсуляция данных — Encapsulation

Что означает слово Encapsulation? Корень — капсула. En — предлог в. Инкапсуляция — это буквально помещение в капсулу. Что помещается в капсулу? Данные и действия над ними: переменные и функции. Инкапсуляция — связывание данных и функций. Давайте ещё раз взглянем на класс Tank:

Собственно, здесь в класс Tank мы поместили переменную ammo и метод Attack. В методе Attack мы изменяем ammo. Это и есть инкапсуляция: члены класса (данные и методы) в одном месте.

В C++ есть ещё одно понятие, которое связано с инкапсуляцией — сокрытие данных. Сокрытие предполагает помещение данных (переменных класса) в область, в которой они не будут видимы в других частях программы. Для сокрытия используются спецификаторы доступа (access specifiers). Ключевые слова public и private и есть спецификаторы доступа. public говорит, что весь следующий блок будет видим за пределами определения класса. private говорит, что только методы класса имеют доступ к данным блока. Пример:

Здесь мы видим, что объект может получить доступ только к членам класса, находящимся в блоке public. При попытке обратиться к членам класса (и переменным, и методам) блока private, компилятор выдаст ошибку. При этом внутри любого метода класса мы можем обращаться к членам блока private. В методе Move мы изменяем скрытые переменные x и y.

Хороший стиль программирования в ООП предполагает сокрытие всех данных. Как тогда задавать значения скрытых данных и получать доступ к ним? Для этого используются методы setters и getters.

Setters and Getters

Setters и Getters сложно красиво перевести на русский. В своих уроках я буду использовать английские обозначения для них. Setter (set — установить) — это метод, который устанавливает значение переменной класса. Getter (get — получить) — метод, который возвращает значение переменной:

Имена не обязательно должны включать Set и Get. Использование setters и getters приводит к увеличению количества кода. Можно ли обойтись без инкапсуляции и объявить все данные в блоке public? Да, можно. Но данная экономия кода имеет свои негативные последствия. Мы будем подробно обсуждать данный вопрос, когда будем говорить об интерфейсах.

Следующая концепция ООП — наследование.

Наследование (Inheritance) в C++

Производный класс не может получить доступ к private членам. Поэтому в классе Unit используется спецификатор protected. Данный спецификатор разрешает доступ к данным внутри класса и внутри дочерних классов, private же разрешает доступ только в методах самого класса.

При наследовании производный класс имеет доступ ко всем членам (public и protected) базового класса. Именно поэтому мы можем вызвать метод Move для объекта типа Archer.

Обратите внимание, как происходит наследование. При определении дочернего класса, после имени ставится двоеточие, слово public и имя базового класса. В следущем уроке мы рассмотрим для чего здесь нужно слово public.

Полиморфизм (Polymorphism)

Наследование открывает доступ к полиморфизму. Poly — много, morph — форма. Это очень мощная техника, которую мы будем использовать постоянно.

Полиморфизм позволяет поместить в массив разные типы данных:

Мы создали массив указателей на Unit. Но C++ позволяет поместить в такой указатель и указатель на любой дочерний классс. Данная техника будет особенно полезна, когда мы изучим виртуальные функции.

Заключение

Классы позволяют легко моделировать лубую предметную область. Иногда лучше избежать использование ООП, но об этом мы поговорим в другой раз.

В следующем уроке мы познакомимся с более сложными концепциями, касающимися классов: виртуалье методы, шаблоны, статичные члены. Впоследствии мы увидим, как классы используютя в DirectX.

Единственное отличие между классом и структурой в C++: по умолчанию в структуре используется спецификатор доступа public, а в классе — private. Часто в коде вы будете видеть, что структуры используются без методов, чисто для описания каких-либо сущностей. Но это делать необязательно это всего лишь соглашение.

Классы в C++ — урок 10

Весь реальный мир состоит из объектов. Города состоят из районов, в каждом районе есть свои названия улиц, на каждой улице находятся жилые дома, которые также состоят из объектов.

Практически любой материальный предмет можно представить в виде совокупности объектов, из которых он состоит. Допустим, что нам нужно написать программу для учета успеваемости студентов. Можно представить группу студентов, как класс языка C++. Назовем его Students .

Основные понятия

Классы в программировании состоят из свойств и методов. Свойства — это любые данные, которыми можно характеризовать объект класса. В нашем случае, объектом класса является студент, а его свойствами — имя, фамилия, оценки и средний балл.

У каждого студента есть имя — name и фамилия last_name . Также, у него есть промежуточные оценки за весь семестр. Эти оценки мы будем записывать в целочисленный массив из пяти элементов. После того, как все пять оценок будут проставлены, определим средний балл успеваемости студента за весь семестр — свойство average_ball .

Методы — это функции, которые могут выполнять какие-либо действия над данными (свойствами) класса. Добавим в наш класс функцию calculate_average_ball() , которая будет определять средний балл успеваемости ученика.

  • Методы класса — это его функции.
  • Свойства класса — его переменные.

Функция calculate_average_ball() просто делит сумму всех промежуточных оценок на их количество.

Модификаторы доступа public и private

Все свойства и методы классов имеют права доступа. По умолчанию, все содержимое класса является доступным для чтения и записи только для него самого. Для того, чтобы разрешить доступ к данным класса извне, используют модификатор доступа public . Все функции и переменные, которые находятся после модификатора public , становятся доступными из всех частей программы.

Закрытые данные класса размещаются после модификатора доступа private . Если отсутствует модификатор public , то все функции и переменные, по умолчанию являются закрытыми (как в первом примере).

Обычно, приватными делают все свойства класса, а публичными — его методы. Все действия с закрытыми свойствами класса реализуются через его методы. Рассмотрим следующий код.

Мы не можем напрямую обращаться к закрытым данными класса. Работать с этими данными можно только посредством методов этого класса. В примере выше, мы используем функцию get_average_ball() для получения средней оценки студента, и set_average_ball() для выставления этой оценки.

Функция set_average_ball() принимает средний балл в качестве параметра и присваивает его значение закрытой переменной average_ball . Функция get_average_ball() просто возвращает значение этой переменной.

Программа учета успеваемости студентов

Создадим программу, которая будет заниматься учетом успеваемости студентов в группе. Создайте заголовочный файл students.h, в котором будет находиться класс Students .

Мы добавили в наш класс новые методы, а также сделали приватными все его свойства. Функция set_name() сохраняет имя студента в переменной name , а get_name() возвращает значение этой переменной. Принцип работы функций set_last_name() и get_last_name() аналогичен.

Функция set_scores() принимает массив с промежуточными оценками и сохраняет их в приватную переменную int scores[5] .

Теперь создайте файл main.cpp со следующим содержимым.

В самом начале программы создается объект класса Students . Дело в том, что сам класс является только описанием его объекта. Класс Students является описанием любого из студентов, у которого есть имя, фамилия и возможность получения оценок.

Читать еще:  Basic это язык программирования

Объект класса Students характеризует конкретного студента. Если мы захотим выставить оценки всем ученикам в группе, то будем создавать новый объект для каждого из них. Использование классов очень хорошо подходит для описания объектов реального мира.

После создания объекта student , мы вводим с клавиатуры фамилию, имя и промежуточные оценки для конкретного ученика. Пускай это будет Вася Пупкин, у которого есть пять оценок за семестр — две тройки, две четверки и одна пятерка.

Введенные данные мы передаем set-функциям, которые присваивают их закрытым переменным класса. После того, как были введены промежуточные оценки, мы высчитываем средний балл на основе этих оценок, а затем сохраняем это значение в закрытом свойстве average_ball , с помощью функции set_average_ball() .

Скомпилируйте и запустите программу.

Отделение данных от логики

Вынесем реализацию всех методов класса в отдельный файл students.cpp.

А в заголовочном файле students.h оставим только прототипы этих методов.

Такой подход называется абстракцией данных — одного из фундаментальных принципов объектно-ориентированного программирования. К примеру, если кто-то другой захочет использовать наш класс в своем коде, ему не обязательно знать, как именно высчитывается средний балл. Он просто будет использовать функцию calculate_average_ball() из второго примера, не вникая в алгоритм ее работы.

Над крупными проектами обычно работает несколько программистов. Каждый из них занимается написанием определенной части продукта. В таких масштабах кода, одному человеку практически нереально запомнить, как работает каждая из внутренних функций проекта. В нашей программе, мы используем оператор потокового вывода cout , не задумываясь о том, как он реализован на низком уровне. Кроме того, отделение данных от логики является хорошим тоном программирования.

В начале обучения мы говорили о пространствах имен (namespaces). Каждый класс в C++ использует свое пространство имен. Это сделано для того, чтобы избежать конфликтов при именовании переменных и функций. В файле students.cpp мы используем оператор принадлежности :: перед именем каждой функции. Это делается для того, чтобы указать компилятору, что эти функции принадлежат классу Students .

Создание объекта через указатель

При создании объекта, лучше не копировать память для него, а выделять ее в в куче с помощью указателя. И освобождать ее после того, как мы закончили работу с объектом. Реализуем это в нашей программе, немного изменив содержимое файла main.cpp.

При создании статического объекта, для доступа к его методам и свойствам, используют операция прямого обращения — « . » (символ точки). Если же память для объекта выделяется посредством указателя, то для доступа к его методам и свойствам используется оператор косвенного обращения — « -> ».

Конструктор и деструктор класса

Конструктор класса — это специальная функция, которая автоматически вызывается сразу после создания объекта этого класса. Он не имеет типа возвращаемого значения и должен называться также, как класс, в котором он находится. По умолчанию, заполним двойками массив с промежуточными оценками студента.

Мы можем исправить двойки, если ученик будет хорошо себя вести, и вовремя сдавать домашние задания. А на «нет» и суда нет 🙂

Деструктор класса вызывается при уничтожении объекта. Имя деструктора аналогично имени конструктора, только в начале ставится знак тильды

Методы класса

Метод класса – это именованный блок выполняемого кода (набор операторов), который может быть вызван на выполнение из разных частей программы. При вызове метода он выполняет свой код, а затем возвращает управление тому коду, который его вызвал. Методы также могут возвращать некоторое значение.

Методы описывают поведение объектов класса. Два объекта одного класса имеют один и тот же набор методов. В описании метода класса выделяют две части – заголовок и тело метода:

Заголовок метода описывается следующим образом:

[режим доступа][модификаторы] имя_метода ([список_формальных_параметров])

Тип результата и список формальных параметров составляют сигнатуру метода. Следует отметить, что в сигнатуру не входят ни имя метода, ни имена параметров. Квадратные скобки в описании заголовка метода показывают, что режим доступа, модификаторы и параметры могут быть опущены при описании метода. Обязательным при описании заголовка является указание типа результата, имени метода и круглых скобок, наличие которых необходимо даже в том случае, если сам список формальных параметров отсутствует. Формально тип результата метода указывается всегда, но ключевое слово void означает отсутствие какого-либо результата. Вот несколько простейших примеров описания методов:

void A(int р) (. ) int В() <. >public void С()

Список формальных параметров метода может быть пустым, что является обычным для методов класса. Список может содержать фиксированное число параметров, разделяемых символом запятая. Объявление формального параметра имеет следующий вид:

[ref | out | params] имя_параметра

Обязательным является указание типа и имени параметра. Никаких ограничений на тип параметра нс накладывается.

Несмотря на фиксированное число формальных параметров, есть возможность при вызове метода передавать ему произвольное число фактических параметров. Для реализации этой возможности в списке формальных параметров необходимо задать ключевое слово params. Оно задастся один раз и указывается только для последнего параметра списка, объявляемого как массив произвольного типа. При вызове метода этому формальному параметру соответствует массив, содержащий произвольное число передаваемых фактических параметров.

Содержательно все параметры метода разделяются на три группы: входные, выходные и обновляемые. Входные параметры передают информацию методу, их значения в теле метода только читаются. Входные параметры задаются без ключевых слов out и ref.

Выходные параметры представляют собой результаты метода, они получают значения в ходе работы метода. Выходные параметры всегда должны сопровождаться ключевым словом out. Выходным параметрам в теле метода обязательно должно присваиваться некоторое значение. В противном случае возникает ошибка уже на этапе компиляции.

Обновляемые параметры выполняют обе функции. Их значения используются в ходе вычислений и обновляются в результате работы метода. Обновляемые параметры сопровождаться ключевым словом ref.

Для примера рассмотрим следующую группу методов: void A(out long р2, int p1) < p2 = (long) Math.Pow(p1,3);

Console. WriteLinefMeTOA A-1″);

void A(out long p2, params int() p) <

Рассмотрим только заголовки методов. Все методы закрыты, поскольку объявлены без модификатора доступа. Перегруженные методы с именем А нс возвращают результирующее значение, а метод F – возвращает значение. Оба перегруженных метода А() имеют разную сигнатуру. Хотя имена и число параметров у всех методов одинаковы, но типы и ключевые слова, предшествующие параметрам, различны. Первый параметр у обоих перегруженных методов выходной и сопровождается ключевым словом out, в теле метода этому параметру присваивается значение.

Параметр функции F – обновляемый, он снабжен ключевым словом ref, в теле функции используется его значение для получения результата функции, но и само значение параметра изменяется в теле функции. Один метод из группы перегруженных методов использует ключевое слово params для своего последнего параметра.

Методы класса имеют значительно меньше параметров, чем методы в обычном процедурном стиле программирования, когда не используется концепция классов. Это связано с тем, что методы класса используются для работы с данными класса, которому они принадлежат. Все поля доступны любому методу по определению. Нужно четко понимать, что в момент выполнения программной системы работа идет не с классом вообще, а с конкретными объектами – экземплярами класса. Из полей соответствующего объекта (цели вызова) извлекается информация, нужная методу в момент вызова, а работа метода чаще всего сводится к обновлению значений полей этого объекта. Поэтому очевидно, что методу не нужно через входные параметры передавать информацию, содержащуюся в полях объекта. Если в результате работы метода обновляется значение некоторого поля, то также не нужен никакой выходной параметр.

Ссылка на основную публикацию
Adblock
detector
×
×