No Image

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

СОДЕРЖАНИЕ
0 просмотров
10 марта 2020

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

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

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

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

Что за классы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Что дальше

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

Когда мы говорим о языке программирование C# мы подразумеваем ООП. А ООП, как известно, это классы, которые необходимо создавать. Однако как показывает мой личный опыт, далеко не все имеют представление о том, что такое класс в программировании…
Понятие того — что такое класс очень важно. Невозможно писать программы, если Вы не осознаете с чем работаете и не можете объяснить это своими словами. Я постараюсь описать Вам свое видение понятия класса в очень примитивной и грубой форме. Однако, на мой взгляд, только так можно поведать в тексте (не в лекциях, не в видео) начинающим программистам что такое класс.
Класс в программировании — это универсальный конструктор описания объектов и терминов. Под объектами мы подразумеваем как любой объект окружающего нас мира (будь то человек, камень или солнечная система), так и любой несуществующий в природе объект (например описание монстра «запупырки» или набора из четырех целых и одного дробного числа). Под термины же попадают всевозможные определения (например, геометрическая точка, предел, какая-нибудь болезнь).
Заметьте, я не зря выделил фразу «конструктор описания». Класс — по своей сути это не рабочий объект (особенно это видно, если вы программируете на языке C++), класс это абстрактное описание чего-либо. Говоря о «абстрактном описании» мы говорим об объектах в целом, а не о каком-либо конкретном предмете или термине (например, если речь идет о людях — мы говорим о понятии «человек», а не о конкретной личности «Иван Иванов»). Класс так же можно сравнить с подробной шаблонной инструкцией по эксплуатации, которую можно положить вместе с любой покупаемой техникой определенной категории. Для покупателя (пользователя программы) телевизор (объект) — это черный ящик. Конечному пользователю не нужно знать, как устроено внутри его приобретение, но ему нужно знать, что и как с этим можно делать на уровне пользования. С другой стороны существует и производитель данного телевизора (разработчик, создавший, и возможно расширивший, объект класса телевизор), который обязан иметь определенный набор знаний о производимом изделии (то что должно быть у всех телевизоров), но при этом не ограничивающийся только ими (создается инструкция на конкретную модель телевизора). Есть еще и третья сторона — изобретатель телевизора (разработчик создавший класс). Именно он описывает то, что должно быть у телевизора и как это должно работать (создает инструкцию для телевизора в целом как для категории товара, а не на конкретную модель).
Разрабатывая программно обеспечение, Вы часто будете выступать за вторую и третью стороны. Вам нужно будет и создавать классы и использовать их, а так же расширять их базовый функционал. Поэтому очень важно прорабатывать структуру вашего класса, чтобы она была удобна в использовании и легко дополнялась новыми возможностями.
Когда перед Вами стоит задача создать класс, который будет описывать существующий объект — не стоит изобретать велосипед. Природа или человечество уже придумали необходимую вам «инструкцию», старайтесь придерживаться ее. Например, если Вам нужно создать класс, описывающий точку в двухмерном пространстве» не нужно наделять ее магическими свойствами. Точка базовый элемент, который описывается своей позицией по оси Х и Y. Не нужно усложнять это определение. Так же не нужно придумывать «новые» имена осям координат (например, менять X на V, а Y на A) — лучше вы точно никому не сделаете. Так же, возможно, Вам наоборот лучше упросить описание под свой конкретный случай. В итоге пишите такой код, и этого будет более чем достаточно:

Читайте также:  Веб камеры в сауне в реальном времени

С точкой все более и менее понятно, однако давайте рассмотрим процесс создания и использования классов на более сложном примере. Причем рассмотрим данный процесс со всех трех сторон.

Задача: создать класс «Телевизор».

Разработка класса Телевизор
Будучи разработчиком (изобретателем телевизора), перед которым стоит такая задача, нужно сразу отметить для себя, что понятие «Телевизор» вполне себе стандартизировано. Сам телевизор уже изобретен, нам нужно лишь «изобрести» класс. Мы все всё знаем о телевизорах и что у них может быть, а так же что они должны уметь делать. Например мы слету можем сказать, что у телевизоров есть название модели, производитель, вес, цвет и некоторые другие свойства. Так же мы знаем что телевизор может менять свою громкость, работать с разными каналами. Еще раз акцентирую Ваше внимание — Мы, как разработчики (в нашем случае телевизора), оперируем общими понятиями. Мы создаем шаблонную инструкцию для категории товаров «телевизор». Мы отпустим данную инструкцию в свободное плаванье, чтобы другие изобретатели смогли создавать свои телевизоры, подставляя нужные значения в наш шаблон, и, при необходимости, добавляя новые функциональные возможности и свойства.

Пример класса телевизор:

Использование класса Телевизор
Отпустив данный шаблон в свободное плаванье, мы уже можем создавать различные телевизоры и работать с ними, используя их возможности. Т.е. теперь мы выступаем в качестве 2ой стороны (разработчика, использующего объекты того или иного класса). Для наглядности опишем наши действия будто мы заводе 🙂

ООП – Организация Освобождения Палестины.
Аббревиатура.

Резонный вопрос – почему так поздно приступаем к знакомству с ООП? Я тоже считаю, что некоторые главы книги только бы выиграли от их изложения в объектно-ориентированной нотации. Но, сказавши «а», следовало бы сказать и «б», т.е. пришлось бы полностью изложить принципы ООП, а это было бы не совсем правильно:

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

многие механизмы объектно-ориентированного Си прекрасно иллюстрируются средствами классического Си, чтобы понимать первое, нужно знать второе;

все предыдущие главы иллюстрированы небольшими по объему программами, для которых объектно-ориентированная нотация (именно как для примеров) не обязательна;

ООП – это постановка процесса программирования «с ног на голову», (или с головы на ноги), а это лучше сделать не в середине изложения материала;

И, наконец, такой «монстр» как Си++, пытающийся сочетать в себе все и вся, имеет не совсем удобную, излишне открытую и довольно громоздкую объектно-ориентированную нотацию. Поэтому данный материал следует рассматривать как приглашение к знакомству с тотальными средами ООП, например, Java или C#.

10.1 Объекты и классы

Объект, метод, класс: определения и свойства

«Классами называются большие группы людей, различающиеся по их месту в исторически определен­ной системе общественного производства, по их отношению) к средствам произ­водства, по их роли в общественной организации труда, а следователь­но, по способам получения и размерам той доли общественного богатства, которой они располагают» Ленинское определение классов.

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

Прописные истины объектно-ориентированного подхода

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

для каждого объекта создается экземпляр данных;

методы класса, с которыми работает объект, представляют собой единственный экземпляр программного кода в сегменте команд, который одинаково выполняется для всех объектов (разделяется ими);

при вызове метода объект, для которого он выполняется, идентифицируется указателем текущего объекта this, задающим контекст текущего объекта.

Таким образом, связка «объект-метод» преобразуется в традиционную последовательность действий: «вызов функции – метода класса с фактическим параметром – указателем на текущий объект».

int a; // struct A < int a; >;

public: vo > // void A::F(A *this) < this->a++; >

если элементы данных класса имеют взаимосвязанные значения, то класс должен поддерживать установленные для них соглашения;

если объект данных класса ссылается на внешние структуры данных, то при синтаксическом копировании объекта необходимо обеспечить независимость связанной структуры данных в объекте-копии (создать ее копию или обеспечить разделение – см. «конструктор копирования»;

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


рис. 101-1. Объект: граница ответственности транслятора и программы

double * pd ; // Внутренняя СД – дин. массив коэффициентов

public : void add ( double D 2[], int n 2)<> // Нарушение закрытости – параметр – внутренняя СД

void add ( poly & T )<> // Правильно: параметр – объект того же класса

По отношению к методам это означает, что интерфейс класса (набор методов) должен быть максимально разнообразен, методы должны сочетаться в любых комбинациях, давая широкое разнообразие возможностей работы с объектом.

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

Читайте также:  Туалет от билла гейтса

double * pd ; // Внутренняя СД – дин. массив коэффициентов

public : poly () < n =0; pd = NULL ; >// Нежелательно: NULL – отсутствие массива

«Ложась спать, программист ставит рядом два стакана: один полный – если захочет пить, и один пустой – если не захочет». Анекдот в тему.

// Класс степенного полинома – заголовок класса (объявление)

int n; // степень полинома

double *pd; // динамический массив коэффициентов

double & get ( int k ); // получение ссылки на коэффициент

void add ( poly & T ); // сложение объектов (1=1+2)

void mul ( poly & T ); // умножение объектов объектов (1=1+2)

Целостность объекта. Конструктор. Деструктор

Требование целостности и корректности объекта означают, что объект – это нечто большее, чем просто переменная. При создании переменной ее инициализация вовсе не обязательна, в то время как создание объекта должно сопровождаться установлением его начального состояния (инициализация данных, резервирование памяти, ресурсов, установление связей и т.д.). Аналогичные обратные действия необходимо выполнить при его уничтожении перед освобождением памяти. С этой целью в классе вводятся специальные методы – конструкторы и деструктор. Их имена совпадают с именем класса. Конструкторов для данного класса может быть сколь угодно много, они отличаются формальными параметрами, деструктор же всегда один и имеет имя, предваренное символом "

". Если конструктор имеет формальные параметры, то в определении переменной-объекта после ее имени должны присутствовать в скобках значения фактических параметров.

// Класс степенного полинома – конструкторы и деструктор

int n; // степень полинома

double *pd; // динамический массив коэффициентов

n=0; // с нулевым коэффициентом

n=m; // с нулевыми коэффициентами

load(n0,p); > // используется вспомогательный метод load

load(T.n, T.pd); > // (конструктор копирования)

Момент вызова конструктора и деструктора определяется временем создания и уничтожения объектов:

для автоматических объектов — конструктор вызывается при входе в функцию (блок), деструктор — при выходе из него;

для динамических объектов — конструктор вызывается при выполнении оператора new, деструктор — при выполнении оператора delete.

В Си++ возможно определение массива объектов класса. При этом конструктор и деструктор автоматически вызываются в цикле для каждого элемента массива и не должны иметь параметров. При выполнении оператора delete для указателя на массив объектов его необходимо предварять скобками.

struct poly < . >; // определение класса

poly a,b(6), c (3, D ); // Статические объекты – конструкторы

// пустой полином, заданной размерности и из массива

poly *p,* q ; // Указатели на объект

poly c,d( c ); // Автоматические объекты

p = new poly ; // Динамический объект

q = new poly [ n ]; // Динамический массив объектов

delete p; // Уничтожение динамического объекта

delete [] q ; // Уничтожение динамического массива объектов

> // Уничтожение автоматических объектов

Замечание: процесс конструирования «вложен» в процесс выделением памяти под переменную. Конструктор вызывается сразу же после выделения памяти, а деструктор – перед ее освобождением.

A(int a1) // Конструктор

A &INC() < a++; return *this; >// Метод класса — инкремент

Класс – структурированный тип с ограниченным доступом

«Настоящий» классы в Си++ отличается от структурированного типа одной единственной мелочью: в классе вводятся ограничения доступа. Естественно, это синтаксические ограничения, и при желании их можно исключить простым редактированием заголовка класса. Это «дисциплинирующие» ограничения, позволяющие установить зоны ответственности программистов – разработчика класса и пользователя класса, обеспечить необходимую закрытость.

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

Формально класс отличается от структурированного типа ключевым словом class (вместо struct ) и наличием двух областей доступа в теле класса:

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

открытая (общая) часть класса допускает любой доступ, в том числе и внешний. Она всегда явно обозначается меткой public.

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

// Класс степенного полинома

int n; // степень полинома

double *pd; // динамический массив коэффициентов

public:… // метка открытой части

Другие варианты размещения данных и методов в личной и общей части класса встречаются реже, но тоже обоснованы:

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

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

Таким образом, в первом приближении класс отличается от структуры четко определенным интерфейсом доступа к его элементам. И наоборот, структура — это класс без личной части.

Иногда требуется ввести исключения из правил доступа, когда некоторой функции или классу требуется разрешить доступ к личной части объекта класса. Тогда в определении класса, к объектам которого разрешается такой доступ, должно быть объявление функции или другого класса как «дружественных». Это согласуется с тем принципом, что сам класс определяет права доступа к своим объектам «со стороны».

Объявление дружественной функции представляет собой прототип функции, переопределяемой операции или имя класса, которым разрешается доступ, предваренное ключевым словом friend.

// Классы и функции, дружественные классу A

int x; // Личная часть класса

. // Все «друзья» имеют доступ к x

friend vo > C::fun(A&);

friend vo > xxx(A&,int);

friend vo > C::operator+( А &);

«Друг – это тот, кто имеет исключительное право лезть тебе в душу (личную часть) в любое время».

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

Читайте также:  Сканер на телефон андроид бесплатно

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

// Класс степенного полинома

int n; // степень полинома

double *pd; // динамический массив коэффициентов

void load(int n0, double p[])<

n=n0; // закрытый метод загрузки массива

pd=new double[n+1]; // — не всегда корректно вызывается

vo > // увеличение размерности полинома

double *pd1=new double[n1+1];

for (; i n 1; i ++) pd 1[ i ]=0;// прописать старшие коэффициенты нулями

delete []pd; // удалить старый массив

pd=pd1; // считать новый за старый

vo > // нормализация — удаление лишних 0

> // память не перераспределяется

public :… // метка открытой части

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

// Класс степенного полинома

int n; // степень полинома

double *pd; // динамический массив коэффициентов

static double foo=0; // вне пределов массива — ссылка

if ( k k > n ) return foo ; // на "левую" статическую переменную

Взаимодействие данных и алгоритма в ООП

Проблема «Что первично — курица или яйцо?» применительно к программированию звучит как «Что первично: алгоритм (процедура, функция) или обрабатываемые им данные». В традиционной технологии программирования взаимоотношение алгоритм (процедуры, функции) — данные имеют более-менее свободный характер, причем алгоритм является ведущим в этой связке: функция вызывает функцию, передавая данные друг другу по цепочке. Соответственно, технология структурного проектирования, прежде всего, уделяет внимание разработке алгоритма. Она может быть выражена одной фразой – программирование (выполнение программы) «от функции к функции».

В технологии ООП взаимоотношения данных и алгоритма имеют более регулярный характер: во-первых, класс объединяет в себе данные и методы (функции). Во-вторых, схема взаимодействия функций и данных принципиально иная. Метод (функция), вызываемый для одного объекта, как правило, не вызывает другую функцию непосредственно. Для начала он должен иметь доступ к другому объекту (создать, получить указатель, использовать внутренний объект в текущем и т.д.), после чего он уже может вызвать для него один из известных методов. Следовательно, структура программы определяется взаимодействием объектов различных классов между собой, а процесс выполнения программы выражается фразой «объект-метод-объект».


рис.101-4. Программирование в цепочке «объект-метод-объект»

Особенности модульного проектирования в технологии ООП

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

· в заголовке класса может присутствовать объявление метода – заголовок со списком типов параметров (прототип), ограниченный точкой с запятой. Это означает, что в заголовочнике упоминается только факт его наличия (с заданным именем и интерфейсом). Тогда в файле тела класса должно быть определение метода, содержащее его заголовок и тело. Заголовок повторяет объявление с одним маленьким отличием: имя метода дается в полной форме в виде имя_класса::имя_метода;

· файл тела класса должен подключать свой заголовочный файл директивой include ;

· для того, чтобы другой класс или main могли создавать объекты некоторого класса и применять к ним методы, необходимо подключать заголовочный файл директивой include ;

· все имена заголовочных файлов и файлов тела класса должны быть включены в проект;

int a; // Данные класса

void add ( A &); // Объявление (прототип) метода

A mul ( A &); // Объявление (прототип) метода

//————————Определение методов класса – файл A . cpp

# include “ A . h ” // Подключение собственного заголовочника

tmp . a *= T . a ; // заголовок с полным именем и тело

//———————— Доступ из другого класса – файл B . h

# include “ A . h ” // Подключение заголовочника класса A

# include “ A . h ” // Подключение заголовочника класса A

A aa , bb ; // Создание объектов класса A

aa . add ( bb ); // Работа с объектами класса A

Естественно, никто не запрещает «свалить все классы в одну кучу», не используя проекта. Для небольших программ это простительно, но не эстетично.

Лабораторный практикум

Разработать класс для требуемого типа данных: внутреннее представление данных, конструкторы, деструктор, методы ввода/вывода, изменения содержимого отдельных элементов. Необходимый материал для вар.14- 18 см . в 9.1.

1. Правильная дробь, представленная целой частью, числителем и знаменателем.

3. Целое число, представленное в виде массива байтов. .Каждый байт хранит 2 цифры числа (часть числа в диапазоне 0..99). Знак числа представлен отдельно.

4. Целое положительное число, представленное в виде массива его простых множителей (произведение которых дает это число).

5. Целое положительное число, представленное в виде массива остатков от деления на первые n 6. Вектор на плоскости, представленный в полярной системе координат (длина, угол поворота).

7. Вещественное число в эспоненциальной форме: нормализованная дробная часть (в диапазоне 0.99. 0.1) — double и целый показатель степени — int.

8. Матрица переменной размерности, представленная динамическим массивом указателей на строки матрицы (линейные динамические массивы).

9. Матрица переменной размерности, представленная динамическим массивом, в котором строки матрицы расположены последовательно друг за другом.

10. Разреженная матрица переменной размерности, ненулевые коэффициенты представлены динамическим массивом с элементами (x,y,v) координаты, значение.

11. Разреженная матрица переменной размерности, ненулевые коэффициенты представлены односвязным списком с элементами (x,y,v) координаты, значение.

12. Разреженная матрица переменной размерности, ненулевые коэффициенты представлены двусвязным циклическим списком с элементами (x,y,v) координаты, значение.

13. Множество, элементами которого являются целые числа. Операции объединения и пересечения множеств, добавления элемента, проверки на вхождение, разности множеств.

14. Целые произвольной длины со знаком во внешней форме представления в виде строки цифр в прямом коде. Знак представлен отдельным элементом данных.

15. Целые произвольной длины со знаком во внешней форме представления в виде строки цифр в прямом коде. Знак представлен старшей цифрой (0 /1).

16. Целые произвольной длины со знаком во внешней форме представления в виде строки цифр в дополнительном коде.

17. Целые произвольной длины во внутреннем двоичном представлении (динамический массив байтов) в прямом коде. Знак представлен отдельным элементом данных.

18. Целые произвольной длины во внутреннем двоичном представлении (динамический массив байтов) в дополнительном коде.

Комментировать
0 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
No Image Компьютеры
0 комментариев
Adblock detector