ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 19.04.2024

Просмотров: 184

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

СОДЕРЖАНИЕ

1 Основные принципы перегрузки операций

Запреты на перегрузку операций

3 Структуры

Доступ к элементам структур

Динамическое распределение памяти

Связанные списки

Очереди

7. Программные продукты и их основные характеристики: основные понятия программного обеспечения; характеристики программных продуктов; защита программных продуктов; классификация программных продуктов

4. Классы программных продуктов

1) Составление технического задания на программирование

2) Составление технического проекта

3) Создание рабочей документации (рабочего проекта)

4) Ввод в действие

1) Диалоговый режим

2) Графический интерфейс пользователя

9. Сети эвм и протоколы передачи информации:

10. Экспертные системы: архитектура, типы решаемых задач, методика построения, области применения. Различные подходы к построению систем ии.

11. Понятие модели данных. Иерархическая, сетевая, реляционная, объектная модель. Типы структур данных. Операции над данными. Ограничения целостности.

2.3. Иерархическая модель данных (имд)

12. Нормализация отношений. Нормальные формы. Запросы и операторы манипулирования данными. Язык запросов sql.

1 Основные принципы перегрузки операций

Ранее мы познакомились с классами С++ и с абстрактными типами данных (ADT). Операции с объектами класса (т.е. представителями ADT) осуществлялись посредством посылки сообщений объектам (в форме вы­зова функций-элементов). Нотация такого вызова функции становится гро­моздкой для определенных категорий классов, в особенности для математиче­ских. Чтобы оперировать с объектами таких классов, было бы удобно исполь­зовать широкий набор встроенных операций С++. В этой лекции мы пока­жем, как разрешить операциям С++ работать с объектами класса. Этот про­цесс называется перегрузкой операций и является прямым и естественным пу­тем к расширению С++ за счет этих новых возможностей.

Операция << в С++ может иметь различный смысл и используется в каче­стве операции передачи в поток и операции сдвига влево. Это пример перегру­женной операции. Операция >> также перегружена, поскольку она использу­ется как операция извлечения из потока и как операция правого сдвига. Обе эти операции перегружаются в библиотеке классов С++. Сам по себе С++ уже перегружает операции + и -. Эти операции выполняют различные функции, которые зависят от контекста применения - в целочисленной арифметике, арифметике чисел с плавающей точкой и арифметике указателей.

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

Несмотря на то, что перегрузка операций может восприниматься как не­кая экзотическая возможность, большинство программистов неявно использу­ют перегруженные операции. Например, операция плюс (+) работает сущест­венно различным образом с целыми, числами с плавающей точкой и числами с двойной точностью. Но плюс, тем не менее, прекрасно работает с переменны­ми типа int, float и double, а также с числами других встроенных типов, по­скольку операция плюс (+) перегружена уже в самом языке С++.


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

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

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


Запреты на перегрузку операций

Большая часть операций С++ может быть перегружена. Эти операции приведены ниже.

Операции, которые могут быть перегружены

+

-

*

/

%

^

&

|

~

!

=

<

>

+=

-=

*=

/=

%=

^=

&=

|=

<<

>>

>>=

<<=

= =

!=

<=

>=

&&

||

++

--

->*

,

->

[]

( )

new

delete

Теперь приведем операции, которые не могут перегружаться.

Операции, которые не могут быть перегружены

.

.*

::

?:

sizeof

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


Ассоциативность операций также не может быть изменена посредством перегрузки. Для перегрузки операций нельзя использовать аргументы по умолчанию.

Отсутствует возможность изменить число операндов, которое подразуме­вает операция. Одноместная операция остается одноместной и при перегрузке, а двухместная остается двухместной. Единственная трехместная операция С++, условная (?:), не может быть перегружена. Каждая из операций &, *, + и - имеет одноместную и двухместную формы, которые могут перегружаться раздельно.

Нельзя создавать новые операции; только существующие операции могут быть перегружены. Это запрещает программисту пользоваться такими попу­лярными нотациями, как операция **, означающая в языке Basic возведение в степень.

При перегрузке ( ), [ ], -> или = перегружающая операцию функция дол­жна объявляться как функция-элемент. Для других операций перегружаю­щие функции могут быть друзьями.

Перегрузка операции присваивания и операции суммирования с целью разрешить такие операции, как

object2 = object2 + object1;

не означает, что автоматически будет перегружена операция +=, чтобы выпол­нялся такой оператор, как

object2 += object1;

Однако такое поведение может быть достигнуто посредством явной пере­грузки операции += для этого класса.

2 Базовые и производные классы.

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

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


Каждый объект производного класса является также объектом базового класса, из которого получен этот производный класс. Однако противополож­ное неверно - объекты базового класса не являются объектами производных классов базового объекта. Мы воспользуемся этим отношением - «объект производного класса является объектом базового класса», чтобы выполнять некоторые интересные преобразования. Например, мы можем перечислить много разных объектов, связанных отношением наследования, в связанном списке объектов базового класса. Это позволит обрабатывать разные объекты одним общим образом. Как мы в дальнейшем увидим в этой и следующей гла­вах, это является одним из важнейших методов объектно-ориентированного программирования.

Мы введем в этой лекции новое средство для управления доступом к элемен­ту - речь идет о защищенном доступе. Производные и дружественные им классы имеют право доступа к защищенным элементам базового класса; у остальных функций такого права нет.

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

Одна проблема с наследованием заключается в том, что производный класс может наследовать открытые функции-элементы, которые не нужно или не следовало бы иметь в «потомстве» явно. Если какой-нибудь элемент ба­зового класса не подходит для производного класса, этот элемент может быть переопределен в самом производном классе с соответствующей реализацией.

Часто объект одного класса «является» также и объектом другого класса. Прямоугольник - rectangle, конечно же, является четырехугольником - quadrilateral (как являются и квадрат, и параллелограмм, и трапеция). Таким образом, о классе Rectangle можно сказать, что он наследует классу Quadrila­teral. В этом смысле класс Quadrilateral называется базовым, а класс Rectan­gle называется производным. Прямоугольник является специальным типом четырехугольника, но нельзя исходя из этого утверждать, что четырехуголь­ник является прямоугольником.