Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Вторая часть лекции.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
592.9 Кб
Скачать

Void sos (int) ;

};

На основе класса в можно по-разному построить производные классы:

class D: public В {

Void func(char);

};

class E: public В {

Void sos (int) ;

};

В классе d чистая виртуальная функция func () заменена конкретной виртуальной функцией того же типа. Функция B::sos() наследуется классом D и доступна в нем и в его методах. Класс D не абстрактный. В классе е переопределена функция B::sos(), а виртуальная функция в ::func() унаследована. Тем самым класс е становится абстрактным и может использоваться только как базовый.

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

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

Например, из абстрактного класса "фигура" можно сформировать класс "треугольник", "окружность" и т.д.

В качестве примера рассмотрим программу, в которой на основе базового класса point построен абстрактный класс figure. В классе figure определены: конструктор, чистая виртуальная функция show () для вывода изображения фигуры, например, на экран дисплея. Кроме того, в класс входят методы hide О - убрать изображение фи­гуры с экрана дисплея и move () - переместить изображение фигуры в заданную точку экрана. Функции hide() и move () обращаются к чис­той виртуальной функции show (). Однако реальное выполнение show () возможно» только после создания производного класса, в ко­тором чистая виртуальная функция show() будет подменена компо­нентной функцией для изображения конкретной фигуры.

Определение абстрактного класса figure (в файле figure. срр):

//FIGURE.CPP - абстрактный класс на базе класса

#include "point.срр"

class figure:

public point

{ public:

// Конструктор абстрактного класса figure:

figure (point p) : point (p.givex () , p.givey()) { }

// Чистая виртуальная функция для будущего

// изображения фигур:

virtual void show() = 0;

// Функция для удаления изображения фигуры:

void hide()

{ int bk, cc;

bk as getbkcolor () ; cc = getcolor () ; setcolor(bk);

show(); // Обращение к чистой виртуальной функции setcolor(cc); }

void move(point p) // Перемещение фигуры в точку "р" { hide (); х = p.givex() ; у = p.givey(); show() ; } };

На базе класса figure определим неабстрактные классы:

//ELLIPS.FIG - конкретный класс "эллипс" на основе figure class ellips : public figure {

int rx,ry; public:

// Конструктор:

ellips (point d, int radx, int rady): figure(d)

{ rx = radx; ry = rady; }

void *how()

{ ellipse(x,y,0,360,rx,ry);

return; } };

//CIRC.FIG - конкретный класс "окружность"

class circ: public figure {

int radius; public:

// Конструктор:

circ(point e, int rad): figure(e) { radius = rad; )

void show() { circle(x,y,radius); } };

В следующей программе используются все три класса:

//Р10-08.СРР - абстрактные классы и чистые виртуальные

// функции

#include <graphics.h>

#include "figure.cpp"

#include "circ.fig"

#include "ellips.fig"

#include <conio.h> // Для функции getch()

void main(void)

{ point A{100,80), B(300,200);

circ С(A,60);

ellips E(B,200,100); { // Переменные для инициализации графики:

int dr = DETECT, mod;

// Инициализация графической системы:

initgraph(&dr, &mod,"c:\\borlandc\\bgi");

// Изобразить точку - point::show():

A.show(); getch ();

// Изобразить точку - point::show() :

В.show(); getch();

// Показать окружность - circ::show():

С.show(); getch();

// Показать эллипс - ellips::show():

E.show() ; getch() ;

// Совместить фигуры - circ: :figure: :move() :

С. move (B) ; getch () ;

// Убрать эллипс - ellips::figure::hide():

E.hide() ; getch () ;

// Убрать окружность - circ::figure::hide():

C.hide() ; getch() ;

} closegraph() ;

}

Графические результаты выполнения показаны на рис. 10.6.

Рис. 10.6. Последовательность изображений на экране при выполнении программы Р10-08. СРР

В программе на базе класса figure определены два производных класса: circ (окружность) и ellips (эллипс). Для обоих классов уна­следованный класс point определяет центры фигур. В обоих классах определены конкретные методы show() и из абстрактного класса figure унаследованы функции move () и hide (). Комментарии к опера­торам основной программы содержат полные (квалифицированные) имена исполняемых функций.

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

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

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

В класс chain входят (рис. 10.7) в качестве компонентов: статиче­ский указатель на последний элемент, уже включенный в список (last), статический указатель на начало списка (begin), указатель в объекте на следующий элемент списка (next), указатель в объекте на абстрактный базовый класс figure (pfig). Параметр конструктора класса chain пусть имеет тип указателя на абстрактный базовый класс figure. В качестве фактических параметров будем использовать ссылки на конкретные объекты классов, производных от абстрактно­го класса figure. Тем самым в односвязный список включаются (рис. 10.7) конкретные фигуры (окружность - класс circ, эллипс - класс ellips).

Рис 10.7. Схема односвязного списка (класс chain,/, объединяющего объекты разных классов.

Текст программы со всеми включениями и определениями:

//Р10-09.СРР - односвязный список объектов разных классов

#include <stdlib.h> // NULL, malloc,...

#include <conio.h> // getch(),...

//#include <iostream.h> // cout,...

#include "point.cpp" // Базовый класс для figure

// Абстрактный класс, производный от point:

#include "figure.cpp"

// Класс, производный от абстрактного figure:

#include "circ.fig"

// Класс, производный от абстрактного figure:

#include "ellips.fig"

// Объекты класса - фигуры, включенные в односвязный

// список:

class chain { // Объект - элемент в односвязном списке

// Указатель на последний элемент в списке:

static chain *last;

// Указатель в объекте на следующий элемент:

chain *next; public:

// Указатель на фигуру, входящую в элемент списка:

figure *pfig;

// Указатель на начало списка:

static chain *begin;

// Конструктор:

chain(figure *p);

// Функция изображает все фигуры списка:

static void showAll(void);

}; // Конец определения класса

// Внешнее описание и инициализация статических // компонентов класса:

chain *chain::begin = NULL; // Начало списка

chain *chain::last = NULL; // Последний элемент в списке