Распознанный текст, спецсимволы и формулы могут содержать ошибки, поэтому с корректным вариантом рекомендуем ознакомиться на отсканированных изображениях учебника выше Также, советуем воспользоваться поиском по сайту, мы уверены, что вы сможете найти больше информации по нужной Вам тематике ДЛЯ СТУДЕНТОВ И ШКОЛЬНИКОВ ЕСТЬ
ZADANIA.TO
6.2. НаследованиеРассмотренный класс CPos не описывает особенностей работы с конкретными графическими примитивами: линией, прямоугольником, эллипсом, а содержит лишь общую для них информацию. Поэтому данный класс следует рассматривать как базовый, на основе которого можно построить дочерние для более детальной работы с графическими объектами, используя механизм наследования.
Предположим, создается дочерний класс с именем CLine для работы с линией на основе базового CPos. Для этого после имени дочернего класса CLine ставится символ ‘:’, а затем пишется имя базового класса CPos с указанием уровня доступа:
В результате наследования с уровнем доступа public класс CLine имеет доступ ко всем переменным и функциям класса CPos, которые не являются частными (private). Ключевое слово public перед именем класса CPos означает, что все общие (public) элементы этого класса остаются с таким же уровнем доступа и в классе CLine. Следует также отметить, что описание класса CPos должно предшествовать описанию класса CLine, а переменные sp_x, sp_y, ep_x и ep_y должны быть описаны в разделе protected для возможности их использования в функции Draw() дочернего класса CLine и в то же время не доступными извне. Класс CLine содержит два конструктора, деструктор и функцию Draw() для рисования линии на экране. При этом процедура задания координат графического объекта целиком находится в базовом классе CPos и по мере необходимости используется в дочернем классе CLine. Такое разделение оказывается удобным, т.к. при описании работы с новыми графическими объектами процедура работы с их координатами будет оставаться одной и той же и находится в одном классе. Если бы в данном случае использовался структурный подход к программированию, то алгоритм работы с координатами графических примитивов пришлось бы прописывать каждый раз для всех типов объектов, что привело бы к заметному усложнению текста программы. Для работы с дочерним классом, также как и с обычным, необходимо создать его экземпляр либо с помощью оператора new, либо через представитель, как показано ниже:
или
При создании нового объекта CLine вызывается сначала конструктор CPos() базового класса, а затем конструктор дочернего – CLine(). Таким образом, создается как бы два объекта: CPos и CLine, но они представляются как единое целое объекта CLine. В представленном классе CLine предусмотрено два конструктора: с параметрами и без них. В случае вызова конструктора с параметрами
вызывается конструктор CPos() базового класса, а затем конструктор CLine(int x1, int y1, int x2, int y2) дочернего, в котором выполняется функция SetParam() для записи значений координат графического объекта. Последние два приведенных примера создания объекта CLine показывают, что вне зависимости от типа вызываемого конструктора дочернего класса всегда вызывается один и тот же конструктор CPos() базового класса, даже если в последнем определено несколько конструкторов. Это не всегда удобно и кроме того, если конструктор CPos() не описан в базовом классе, то создание дочернего класса CLine станет невозможным, т.к. конструктор по умолчанию CPos() не будет найден. Для того чтобы исправить такую ситуацию необходимо в дочернем классе указать, какой именно конструктор базового класса следует вызывать, следующим образом:
В приведенном примере конструктор CLine() будет вызывать конструктор CPos() базового класса, а конструктор CLine(int x1, int y1, int x2, int y2) конструктор CPos(int x1, int y1, int x2, int y2). При этом функция SetParam() в CLine(int x1, int y1, int x2, int y2) может быть опущена, т.к. необходимая инициализация переменных будет выполнена при вызове конструктора CPos(int x1, int y1, int x2, int y2) базового класса. В рассматриваемой задаче программирования графического редактора, класс CPos является вспомогательным, т.е. он служит для создания описания новых классов как базовый. При этом нет необходимости создавать его экземпляр в памяти ЭВМ для непосредственной работы с ним. Поэтому целесообразно защитить его от возможности создания путем помещения конструкторов данного класса в раздел protected. Такие классы называются абстрактными, т.е. они не могут существовать как самостоятельные объекты, а служат для создания новых, дочерних классов. Описание абстактного класса CPos и дочернего от него CLine показано ниже:
Функции классов CPos и CLine можно вызывать, например, через представитель класса CLine, следующим образом:
Обратите внимание, что благодаря полиморфизму, функция SetParam(), заданная в классе CPos, вызывается через представитель line как будто она определена в классе CLine. В результате, единожды объявленная функция SetParam() может быть многократно использована в разных классах, производных от CPos. Для работы с другими графическими примитивами (прямоугольником и эллипсом) подобным образом можно создать дочерние классы от CPos, отличающихся друг от друга реализацией функции Draw():
В результате построения объектов получается следующая иерархия (рис. 6.1).
Рис. 6.1. Иерархия классов графических примитивов У каждого из представленных дочерних объектов CLine, CRect и CEllipse имеется один базовый объект CPos. Вместе с тем язык С++ предоставляет возможность создавать дочерние объекты на основе нескольких базовых, что приводит к концепции множественного наследования. В рамках данной задачи множественное наследование будет иметь смысл, если добавить еще один абстрактный класс с именем CProp, который будет отвечать за свойства графических примитивов: толщина и цвет линии:
Теперь дочерние классы CLine, CRect и CEllipse можно образовывать от двух базовых CPos и CProp, которые являются не связанными друг с другом. Для того чтобы построить класс на основе двух базовых они указываются друг за другом через запятую следующим образом:
Аналогичным образом строятся классы CRect и CEllipse. Здесь следует отметить, что конструктор CLine(int x1, int y1, int x2, int y2, int w, int clr) класса CLine вызывает конструкторы двух базовых классов, которые перечислены через запятую с указанием в них конкретных переменных. Работа с функциями класса CLine через его представитель имеет следующий вид:
Благодаря полиморфизму, функции SetProperty() и SetParam() базовых классов вызываются непосредственно из класса CLine. Видео по теме
|
1 |
Оглавление
|