
- •Void main (){
- •Операции, определенные по умолчанию над структурированными объектами
- •Void binar(unsigned char ch)
- •Void main() { int k;
- •Расширение действия (перегрузка) стандартных операций
- •Доступ к компонентам структурированного объекта
- •Void ff(cl1 cl,cl2 c2) { тело_функции }
- •Void f1(...);
- •Void f2(...);
- •Классы и шаблоны
- •Int size; // Количество элементов в массиве
- •Vector(int); // Конструктор класса vector
- •Имя_параиетризованного_класса
- •Int length;
- •Void main () {
- •Наследование и другие возможности классов Наследование классов
- •2. Множественное наследование и виртуальные базовые классы
- •Void show ()
- •Void hide()
- •Void riesquare(void)
- •Void show()
- •Void hide()
- •Void show(void)
- •Void hide()
- •Void main()
- •Void show() // Изобразить на экране эллипс
- •Void hide() { int cc, bk;
- •Int min(int valuel, int value2)
- •Void show()
- •Void hide() // Убрать изображение с экрана дисплея
- •Void main()
- •3. Виртуальные функции и абстрактные классы
- •Void main (void)
- •Имя_проиаводного_класса: : show ()
- •Иня_объекта_производноро_класса. Show ()
- •Void main(void)
- •Void sos (int) ;
- •Void func(char);
- •Void sos (int) ;
- •Void chain::showAll(void) // Изображение элементов списка
- •Void main()
- •4. Локальные классы
- •Void showSeg() // Изобразить отрезок на экране
- •Void showSquare(void) // изобразить квадрат
- •5. Классы и шаблоны
- •Int size; // Количество элементов в массиве
- •Vector(int); // Конструктор класса vector
- •Имя_параиетризованного_класса
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; // Последний элемент в списке