Отношения между классами: агрегация,
⇐ ПредыдущаяСтр 3 из 3 НАСЛЕДОВАНИЕ, ЗАВИСИМОСТЬ Цель работы
Изучить реализацию на языке С++ отношений между классами: агрегации, наследования, зависимости.
Содержание работы
1. Ознакомиться с отношениями между классами: агрегацией, наследованием, зависимостью, а также с механизмом позднего связывания. 2. Путем модификации программ, разработанных в лабораторных работах № 1, 2, разработать программу такую, чтобы в ней были определены несколько классов, реализующих понятие геометрической фигуры в графической системе: – абстрактный класс «Фигура», содержащий чисто виртуальные функции; – класс «Закрашенный», позволяющий задать кисть, ее параметры и, возможно, осуществить закраску; – класс «Фигура-контур» потомок класса «Фигура»; – класс «Закрашенная фигура» потомок класса «Фигура-контур», класс «Закрашенный» при этом использовать либо как второго родителя (множественное наследование), либо как часть класса «Закрашенная фигура» (агрегация); – класс «Комбинированная фигура», реализующий две вложенные фигуры с закраской между ними. Реализацию классов поместить в отдельный файл. Разработать функцию, демонстрирующую поведение разработанных классов, включая демонстрацию механизма позднего связывания. 3. Подготовить текстовые файлы с разработанной программой, оттранслировать их, собрать и выполнить программу с учетом требований операционных систем и программных оболочек, в которых эта программа выполняется. При необходимости исправить ошибки и вновь повторить технологический процесс решения задачи. 4. Оформить отчет по лабораторной работе. Отчет должен содержать постановку задачи, описание разработанных классов, алгоритм, текст разработанной программы и результаты тестирования.
5. Защитить лабораторную работу, ответив на вопросы преподавателя.
Методические указания Рассмотрим использование механизма наследования для реализации геометрических фигур в графической системе. Сначала опишем наиболее общий класс «Фигура», в котором будут только общие свойства всех фигур.
struct Point; class Shape { protected: Point Сenter; // центр фигуры ... public: virtual void draw () = 0; // чисто виртуальная функция ... };
Описание класса содержит защищенную (protected) часть, элементы (атрибуты и служебные функции) в этой части видимы не только самому классу и его друзьям (как в закрытой части), но и его наследникам. Описание virtual означает, что функция является виртуальной – замещается в классе, производном от данного. Функция, интерфейс вызова которой может быть определен, а реализация – нет, объявляется чисто виртуальной, для чего используется синтаксис «= 0». Для определения класса фигуры-контура «Окружность» мы должны сказать, что она является фигурой (Shape), и указать особые свойства (в том числе определить чисто виртуальные функции).
struct Color; class Circle: public Shape { protected: int Radius; // радиус Color col; // цвет контура ... public: Circle (Point cntr, int rds, Color cl); // конструктор void draw (); // определение чисто виртуальной функции ... };
Класс «Закрашенная окружность» определим как наследника классов «Окружность» и «Закрашенный».
class Filled; class FilledCircle: public Circle, public Filled { public: void draw ();// переопределение чисто виртуальной функции ... };
Класс «Комбинированная фигура», реализующий две вложенные фигуры с закраской между ними, определим как наследника класса «Закрашенная окружность».
class CombiCircle: public FilledCircle { protected: FilledCircle fc; // внутренняя фигура ... public: void draw ();// переопределение чисто виртуальной функции ... };
При определении классов их суперклассы были объявлены нами как открытие (public). В результате открытые и защищенные члены суперкласса становятся открытыми и защищенными членами подкласса. Таким образом, подкласс считается также и подтипом, то есть обязуется выполнять все обязательства суперкласса. В частности, он обеспечивает совместимое с суперклассом подмножество интерфейса и обладает неразличимым с точки зрения клиентов суперкласса поведением.
С наследованием связан особый тип полиморфизма – включение (чистый полиморфизм). Данный тип полиморфизма реализуется при вызове виртуальных функций для указателей (ссылок) на объекты. При открытом наследовании указатель родительского класса может указывать на объекты всех подклассов. Если виртуальная функция имеет различные реализации в подклассах, то выбор, какую ее реализацию вызывать, определяется с учетом выяснения подтипа на этапе выполнения. То есть виртуальная функция вызывается в зависимости не от типа указателя, а от реального типа объекта, на который он указывает. Данная ситуация называется механизмом позднего связывания. Чистый полиморфизм позволяет взаимодействовать с объектом, не зная, к какому конкретному классу он относится. Это происходит за счет общего интерфейса классов в открытой иерархии наследования. Продемонстрируем механизм позднего связывания в построенной нами иерархии классов.
int main (){ Shape *pS; Circle C; FilledCircle FC; CombiCircle CC; ... pS = &C; pS -> draw(); // рS указывает на объект типа Circle, // рисуется фигура-контур pS = &FC; pS -> draw (); рS указывает на объект типа FilledCircle, // рисуется закрашенная фигура pS = &СC; pS -> draw (); рS указывает на объект типа CombiCircle, // рисуется комбинированная фигура } 4. Контрольные вопросы
1. Ассоциация: а. Что такое ассоциация? б. Что такое кратность ассоциации? На какие типы делятся ассоциации в связи с понятием кратности? в. Что такое рефлексивная ассоциация?
2. Агрегация: а. Что такое агрегация (отношение между классами)? б. Что такое композиция?
3. Что такое зависимость?
4. Наследственная иерархия: а. Что такое наследование? б. Что такое виртуальная и чисто виртуальная функция? в. Какие классы называют конкретными, абстрактными?
г. Какие классы называют корневыми, листовыми? д. Для чего вводится защищенная часть класса?
5. Наследование и типизация: а. Что такое открытое (public) наследование? б. Что такое закрытое (private) наследование? в. Что такое защищенное (protected) наследование? г. Допустимо ли присваивание объекту класса-родителя значения класса-потомка? Если да, то каким образом оно реализуется? д. Допустимо ли присваивание объекту класса-потомка значения класса-родителя? Если да, то каким образом оно реализуется? е. Что такое чистый полиморфизм? ж. Что такое повышающее приведение? з. Что такое понижающее приведение?
6. Множественное наследование: а. Что такое множественное наследование? б Что такое конфликт имен? в. Что такое повторное наследование? г. Что такое ромбовидная структура наследования? д. Что такое виртуальное наследование?
ЛАБОРАТОРНАЯ РАБОТА №5 ШАБЛОНЫ Цель работы Изучить понятия шаблона, инстанцирования. Содержание работы 1. Ознакомиться с понятиями шаблона, инстанцирования. 2. Путем модификации программ, разработанных в лабораторных работах № 3, 4, разработать шаблон контейнера для хранения объектов классов, реализующих геометрические фигуры. 2.1. Преобразовать класс-контейнер, разработанный в лабораторной работе №3, в шаблон, так чтобы элементами контейнеров могли быть различные классы, разработанные в лабораторной работе №4 (при различном инстанцировании шаблона). 2.2. Разработать функцию, демонстрирующую поведение разработанного шаблона: провести инстанцирование шаблона для каждого из классов-фигур, продемонстрировать их функционирование. 3. Подготовить текстовые файлы с разработанной программой, оттранслировать их, собрать и выполнить программу с учетом требований операционных систем и программных оболочек, в которых эта программа выполняется. При необходимости исправить ошибки и вновь повторить технологический процесс решения задачи. 4. Оформить отчет по лабораторной работе. Отчет должен содержать постановку задачи, описание разработанных классов, алгоритм, текст разработанной программы и результаты тестирования.
5. Защитить лабораторную работу, ответив на вопросы преподавателя. Методические указания
Преобразуем класс Open_Stack из лабораторной работы №3 в шаблон. Шаблон служит для построения других классов и может быть параметризован другими классами, объектами или операциями.
template <class Type> class Open_Stack { Type* s; int length, top; public: Open_Stack(int n); // конструктор, n – размер стека ~ Open_Stack(); // деструктор void push(const Type el); // помещение элемента в контейнер Type pop(); // возвращение элемента с удалением из контейнера bool find(const Type el); // поиск элемента в контейнере ... };
Префикс template <class Type> делает класс Type параметром объявления, которому этот префикс предшествует. Функции, описываемые вне шаблона, имеют следующий вид.
template <class Type> Open_Stack <Type>:: Open_Stack (int n) {...} template <class Type> Open_Stack <Type>:: ~Open_Stack () {...} template <class Type> void Open_Stack <Type>:: push(const Type el) {...} template <class Type> Type Open_Stack <Type>:: pop() {...} template <class Type> bool Open_Stack <Type>:: find (const Type el) {...}
Инстанцирование – подстановка фактических параметров шаблона вместо формальных. В результате создается конкретный класс, который может иметь экземпляры. Объявим нужные нам стеки.
Open_Stack < Circle* > CircleStack // стек окружностей Open_Stack < FilledCircle* > FilledCircleStack // стек закрашенных // окружностей Open_Stack < CombiCircle* > CombiCircle Stack // стек комбинированных //окружностей
Каждая версия класса, создаваемая по шаблону, содержит одинаковый базовый код; изменяется только то, что связано с параметрами шаблона. При этом для какого-либо типа данных может возникнуть необходимость написать специальный код. В этом случае можно либо предусмотреть для этого типа специальную реализацию отдельных операций, либо полностью переопределить (специализировать) шаблон класса. Так, для специализации операции требуется определить вариант ее кода, указав в заголовке конкретный тип данных.
void Open_Stack < CombiCircle*>:: find(const CombiCircle* el) {...}
При специализации целого класса после описания обобщенного варианта класса помещается полное описание специализированного класса, при этом требуется заново определить все его методы.
class Stack < CombiCircle*> {...} 4. Контрольные вопросы 1. Что такое шаблон класса, как его описать на С++? 2. Что такое инстанцирование, как его описать на С++? 3. Что такое шаблон функции, как его описать на С++? 4. Каковы свойства статической переменной в языке С++? 5. Каково назначение статической функции в языке С++? 6. Что такое утилита, как ее реализовать на С++? 7. Что такое интерфейс? Как его можно описать на С++?
8. Какие отношения могут существовать между интерфейсами, между интерфейсом и классом? 9. Что такое категория классов? 10. Что такое пространство имен в языке С++? Литература
1. Абрамов В.Г., Трифонов Г.Н. Введение в язык Паскаль. – М.: Наука, 1988. 2. Лисицин Д.В. Объектно-ориентированное программирование: Конспект лекций. – Новосибирск: Изд-во НГТУ, 2010. 3. Павловская Т.А. C/C++. Программирование на языке высокого уровня.– СПб.: Питер, 2010. 4. Павловская Т. А., Щупак Ю. А. C++. Объектно-ориентированное программирование: Практикум. – СПб.: Питер, 2008. 5. Подбельский В.В. Язык С++: Учеб. пособие. – М.: Финансы и статистика, 2007. 6. Пол А. Объектно-ориентированное программирование на С++. – СПб.; М.: «Невский диалект» – «Издательство Бином», 1999. 7. Хабибуллин И.Ш. Программирование на языке высокого уровня. C/C++. – СПб.: БХВ-Петербург, 2006. 8. Фридман А.Л. Основы объектно-ориентированного программирования на языке С++. – М.: Горячая линия – Телеком, 2001. 9. Фролов А.В., Фролов Г.В. Графический интерфейс GDI в MS Windows. – М.: «Диалог-МИФИ», 1994. * Элементы, которым соответствует одно и то же хеш-значение, связываются в цепочку – список, а в самом элементе таблицы хранится ссылка на список. ** Под множеством будем подразумевать таблицу, ключами в которой являются сами элементы.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|