Лекция №

Вид материалаЛекция
Подобный материал:
1   2   3   4   5   6   7   8   9   10   11

// является постфиксной.

Iterator operator ++(int)

{

Iterator t(*this); // сохраняем "не увеличенное" значение итератора

P = P->Next; // переходим к следующему эл-ту

return t; // возвращаем "не увеличенное" значение итератора

}


// Префиксная операция декремента. Перемещает итератор к предыдущему эл-ту списка.

Iterator operator --()

{

P = P->Prev; // переходим к предыдущему эл-ту

return *this; // возвращаем "уменьшенный" итератор

}


// Постфиксная операция декремента. Перемещает итератор к предыдущему эл-ту списка.

// Аргумент типа int указывает компилятору, что данная функция-операция operator --

// является постфиксной.

Iterator operator --(int)

{

Iterator t(*this); // сохраняем "не уменьшенное" значение итератора

P = P->Prev; // переходим к предыдущему эл-ту

return t; // возвращаем "не уменьшенное" значение итератора

}


// Операция равенства.

friend bool operator ==(const Iterator& x, const Iterator& y)

{

return x.P == y.P;

}


// Операция неравенства.

friend bool operator !=(const Iterator& x, const Iterator& y)

{

return x.P != y.P;

}


};


Листинг модуля ListNode.h


// Если "ListNode.h" включен вне "List.h",

#ifndef ListInterior

// то выдать ошибку компиляции.

#error "ListNode.h" is internal for "List.h". Do not include directly.

#endif


//template

//class List {

//...


// Узел списка.

struct Node {

T Data; // данные (значение эл-та списка)

Node *Prev, *Next; // указатель на предыдущий и следующий узлы


// Создание отдельного узла.

Node(const T& data)

: Data(data), // копируем данные;

Prev(NULL), // предыдущего и

Next(NULL) // последующего узлов нет

{

} };

Приложение Г

(рекомендуемое)

Листинг модуля Classes.h


//---------------------------------------------------------------------------


#ifndef ClassesH

#define ClassesH


#include


#include "Array.h"

#include "List.h"


//---------------------------------------------------------------------------

// Абстрактный класс "Фигура".

class CFigure {


private:

TColor FColor; // цвет фигуры (используется при цветном изображении)


public:

// Создание фигуры заданного цвета (по умолчанию белый).

CFigure(TColor c = clWhite)

: FColor(c)

{

}


// Деструктор. ОБЯЗАТЕЛЬНО должен быть виртуальным у полиморфных (использующих

// виртуальные функции) классов. См. Unit1.cpp, TForm1::FreeFigures.

virtual ~CFigure()

{

}


// Возвращает цвет фигуры.

TColor Color() const

{

return FColor;

}


// Устанавливает цвет фигуры.

void Color(TColor c)

{

FColor = c;

}


// Изображает фигуру: определяют производные классы, реализующие конкретные фигуры.

// Считается, что фигура отображается текущим цветом пера.

virtual void Draw(TCanvas *canvas) const = 0;


// Изображает фигуру в цвете: устанавливает цвет пера в FColor и вызывает Draw.

virtual void ColorDraw(TCanvas *canvas) const;


};

//---------------------------------------------------------------------------

// Конкретный класс: Точка.

class CPoint: public CFigure {


// Параметры точки являются защищенными элементами, чтобы

// потомки могли обратиться к ним напрямую (для упрощения реализации).

protected:

int FX, FY; // координаты точки


public:

// Создает точку в начале координат.

CPoint()

: FX(0), FY(0)

{

}


// Создает точку с заданными координатами.

CPoint(int x, int y)

: FX(x), FY(y)

{

}


// Считывание/задание координат точки.

int X() const { return FX; }

void X(int x) { FX = x; }

int Y() const { return FY; }

void Y(int y) { FY = y; }


// Изображение точки.

virtual void Draw(TCanvas *canvas) const;


// Изображение точки в цвете: наследуется реализация CFigure.


};

//---------------------------------------------------------------------------

// Конкретный класс: Окружность. От точки наследует координаты центра.

class CCircle: public CPoint {


protected:

int FR; // радиус окружности


public:

// Окружность с центром в начале координат нулевого радиуса.

CCircle()

: FR(0)

{

}


// Окружность с заданными координатами центра и радиусом.

CCircle(int x, int y, int r)

: CPoint(x, y), FR(r)

{

}


// Окружность с центром в заданной точке и указанным радиусом.

CCircle(const CPoint &p, int r)

: CPoint(p), FR(r)

{

}


// Считывание/задание радиуса окружности.

int R() const { return FR; }

void R(int r) { FR = r; }


// Изображение окружности.

virtual void Draw(TCanvas *canvas) const;


// Изображение окружности в цвете: наследуется реализация CFigure.


};

//---------------------------------------------------------------------------

// Конкретный класс: Эллипс. От окружности наследует координаты центра и горизонтальную полуось.

class CEllipse: public CCircle {


protected:

int FVR; // вертикальная полуось


public:

// Эллипс с центром в начале координат с нулевыми полуосями.

CEllipse()

: FVR(0)

{

}


// Эллипс с заданными координатами центра и полуосями.

CEllipse(int x, int y, int r, int vr)

: CCircle(x, y, r), FVR(vr)

{

}


// Эллипс с центром в заданной точке и указанными полуосями.

CEllipse(CPoint &p, int r, int vr)

: CCircle(p, r), FVR(vr)

{

}


// Вытягивание указанной окружности до эллипса с заданной вертикальной полуосью.

CEllipse(CCircle &c, int vr)

: CCircle(c), FVR(vr)

{

}


// Считывание/задание вертикальной полуоси.

int VR() const { return FVR; }

void VR(int vr) { FVR = vr; }


// Изображение эллипса.

virtual void Draw(TCanvas *canvas) const;


// Изображение эллипса в цвете: наследуется реализация CFigure.


};

//---------------------------------------------------------------------------

// Задание синонима типа для конкретного класса: массива точек, определенного по шаблону.

typedef Array PointArray;


// Конкретный класс: Ломаная. Как фигура происходит от CFigure.

// От PointArray наследует возможность задания числа точек-узлов, обращение

// к ним через операцию индексами и проч.

class CPolyline : public CFigure, public PointArray {


public:

// Пустая ломаная (из нуля узлов).

CPolyline()

{

}


// Ломаная из заданного числа узлов с координатами узлов, которые копируются,

// начиная с указанного адреса.

CPolyline(unsigned count, CPoint *coords)

: PointArray(count, coords)

{

}


// Ломаная из заданных в массиве точек узлов.

CPolyline(const PointArray &coords)

: PointArray(coords)

{

}


// Изображение ломаной.

virtual void Draw(TCanvas *canvas) const;


// Изображение ломаной в цвете: наследуется реализация CFigure.


};

//---------------------------------------------------------------------------

// Задание синонима типа для конкретного класса: связного списка указателей

// на CFigure, определенного по шаблону.

typedef List FigureList;


// Конкретный класс: Множество фигур. Как фигура происходит от CFigure.

// От FigureList наследует возможность управления связным списком

// указателей на CFigure.

// Особенности реализации:

// 1) Класс хранит не сами Фигуры, содержащиеся в множестве, а лишь указатели

// на них. Т. е. использующий класс должен сам создавать эти фигуры

// и следить за их корректным уничтожением.

// 2) Т. к. множество не может содержать одинаковых элементов (а список может),

// то FigureList является закрытым базовым классом, чтобы исключить возможность

// использование тех функций списка, которые могут нарушить единственность элементов.

// 3) Класс не дает добавить себя как элемент, что приведет к бесконечной рекурсии

// при вызове функции Draw. Однако, более сложные случаи не отслеживаются, т. е.

// ответственность переносится на использующего класс. Например, множество фигур A

// содержит множество фигур B, а B содержит A.

class CFigureSet : public CFigure, private FigureList {


public:

// Делаем открытыми те элементы FigureList, которые считаем пригодыми для использования

// без изменений.

FigureList::Iterator; // вложенный класс Iterator

FigureList::First; // итератор на первый,

FigureList::Last; // последний и

FigureList::End; // "конечный" элементы

FigureList::Empty; // проверка пустоты

FigureList::Delete; // удаление элемента

FigureList::Clear; // удаление всех элементов


// Пустое множество фигур.

CFigureSet()

{

}


// Изображение множества фигур.

virtual void Draw(TCanvas *canvas) const;


// Изображение множества фигур: реализация в CFigure не подходит.

virtual void ColorDraw(TCanvas *canvas) const;


// Добавление фигуры в множество.

void Add(CFigure &f);


// Операция запятая (левый аргумент - множество фигур, правый - фигура):

// добавление фигур в множество.

CFigureSet& operator ,(CFigure &f)

{

Add(f); // добавляем фигуру

return *this; // возвращаем ссылку на себя, для возможности дальнейшего добавления

}

// Пример. Пусть A - множество фигур; a, b, c, d - фигуры.

// Вычисление выражения A, a, b, c приведет к добалению a, b, c в A.

// Сначала вычисляется (A, a) и a добавляется в A; результат - ссылка на A,

// т. е. дальше вычисляется (A, b) и т. д.


// Операция присваивания множеству фигур фигуры:

// Удаляет все фигуры из множества, добавляет указанную и возвращает ссылку на себя.

// Дальше можно использовать операцию запятая.

CFigureSet& operator =(CFigure &f)

{

Clear(); // удаляем все фигуры

Add(f); // добавляем указанную фигуру

return *this; // возвращаем ссылку на себя, для возможности применения операции запятая

}

// Пример.

// Вычисление выражения A = b, c, d приведет к созданию множества из фигур b, c, d.


// Операция сложения с присваиванием: добавление фигуры в множество.

// Введена для того, чтобы сделать текст программы более понятным.

CFigureSet& operator +=(CFigure &f)

{

Add(f); // добавляем фигуру

return *this; // возвращаем ссылку на себя, для возможности применения операции запятая

}

// Пример.

// Теперь для добавления в множество A фигур a, b, c можно писать A += a, b, c

// вместо A, a, b, c.


};

//---------------------------------------------------------------------------

#endif


Листинг модуля Classes.cpp


//---------------------------------------------------------------------------


#pragma hdrstop


#include "Classes.h"


//---------------------------------------------------------------------------

// CFigure

//---------------------------------------------------------------------------

void CFigure::ColorDraw(TCanvas *canvas) const

{

canvas->Pen->Color = FColor; // задаем цвет пера

Draw(canvas); // изображаем фигуру

}

//---------------------------------------------------------------------------

// CPoint

//---------------------------------------------------------------------------

void CPoint::Draw(TCanvas *canvas) const

{

// Ставим точку цвета пера.

canvas->Pixels[FX][FY] = canvas->Pen->Color;

}

//---------------------------------------------------------------------------

// CCircle

//---------------------------------------------------------------------------

void CCircle::Draw(TCanvas *canvas) const

{

// Делаем кисть пустой и рисуем окружность.

canvas->Brush->Style = bsClear;

canvas->Ellipse(FX - FR, FY - FR, FX + FR, FY + FR);

}

//---------------------------------------------------------------------------

// CEllise

//---------------------------------------------------------------------------

void CEllipse::Draw(TCanvas *canvas) const

{

// Делаем кисть пустой и рисуем эллипс.

canvas->Brush->Style = bsClear;

canvas->Ellipse(FX - FR, FY - FVR, FX + FR, FY + FVR);

}

//---------------------------------------------------------------------------

// CPolyline

//---------------------------------------------------------------------------

void CPolyline::Draw(TCanvas *canvas) const

{

unsigned c = Count();

// Если есть хотя бы один узел, то

if (c) {

// Определяем ссылку l на себя, для удобства обращения к операции индексации.

const CPolyline &l = *this;

// Если узлов больше одного, то изображаем их.

if (c > 1) {

// Перемещаем перо в первый узел.

canvas->MoveTo(l[0].X(), l[0].Y());

// Проводим линии в последующие.

for (unsigned i = 1; i < c; i++)

canvas->LineTo(l[i].X(), l[i].Y());

}

// Ставим точку в последнем узле.

// (Если узел один, то эта точка - вся ломаная.

// Если несколько, то точка требуется, т. к. LineTo последнюю точку не изображает).

const CPoint &p = l[c - 1];

canvas->Pixels[p.X()][p.Y()] = canvas->Pen->Color;

}

}

//---------------------------------------------------------------------------

// CFigureSet

//---------------------------------------------------------------------------

void CFigureSet::Draw(TCanvas *canvas) const

{

// Изображаем все фигуры множества.

// Именно здесь задействуется механизм виртуальных функций. Т. к. мы вызываем

// Draw через указатель на CFigure, то в случае не виртуальной функции Draw,

// вызвалась бы CFigure::Draw. Здесь же вызывается Draw из соответсвующего

// класса. Например, если укатель на CFigure реально хранит адрес CCircle, то

// вызывается CCircle::Draw и т. п.

for (Iterator i = First(); i != End(); i++)

(*i)->Draw(canvas);

}

//---------------------------------------------------------------------------

void CFigureSet::ColorDraw(TCanvas *canvas) const

{

// Изображаем все фигуры множества в цвете.

for (Iterator i = First(); i != End(); i++)

(*i)->ColorDraw(canvas);

}

//---------------------------------------------------------------------------

void CFigureSet::Add(CFigure &f)

{

// p - адрес добавляемой фигуры f.

CFigure *p = &f;

// Пресекаем попытку добавить в множество само множество.

if (this == p) return;

for (Iterator i = First(); i != End(); i++)

// Если указанная фигура уже добавлена, то выходим.

if (*i == p) return;

// Иначе, добавляем адрес фигуры в список.

PushBack(p);

}

//---------------------------------------------------------------------------


#pragma package(smart_init)


Листинг модуля OOPExample.h


//---------------------------------------------------------------------------

#ifndef OOPExampleH

#define OOPExampleH

//---------------------------------------------------------------------------

#include

#include

#include

#include

#include

#include

#include "Classes.h"

//---------------------------------------------------------------------------

class TfrmOOPExample : public TForm

{

__published: // IDE-managed Components

TButton *Create;

TCheckBox *Color;

TColorBox *ColorBox;

TPaintBox *PB;

TPanel *Panel1;

TPanel *Panel2;

TTreeView *TV;

TSplitter *splrMain;

TTimer *FlashTimer;

void __fastcall CreateClick(TObject *Sender);

void __fastcall ColorClick(TObject *Sender);

void __fastcall FormDestroy(TObject *Sender);

void __fastcall ColorBoxClick(TObject *Sender);

void __fastcall FormCreate(TObject *Sender);

void __fastcall PBPaint(TObject *Sender);

void __fastcall TVClick(TObject *Sender);

void __fastcall FlashTimerTimer(TObject *Sender);

private: // User declarations


// Множества выводимых фигур.

CFigureSet RandomSet, // случайно-генерируемое

FixedSet; // заданное


unsigned Flashs; // число миганий выбранной в TV фигуры, умноженное на 2

CFigure *Flash; // адрес мигающей фигуры


// Наполняет множество фигур s случайным числом случайно-сгенерированных фигур.

// Названия созданных фигур добавляются в ветку дерева node.

// recursive - условие, разрешающее генерировать множества фигур.

// Фигуры создаются операцией new.

void CreateFigures(CFigureSet &s, TTreeNode *node, bool recursive);


// Удаляет (операцией delete) фигуры, содержащиеся в множестве фигур s.

void FreeFigures(CFigureSet &s);


// Рисует указанную фигуру заданным в ColorBox цветом если переключатель

// Color включен; иначе фигура изображается ее собственным цветом.

void DrawFigure(CFigure &f);


public: // User declarations

__fastcall TfrmOOPExample(TComponent* Owner);

};

//---------------------------------------------------------------------------

extern PACKAGE TfrmOOPExample *frmOOPExample;

//---------------------------------------------------------------------------

#endif


Листинг модуля OOPExample.cpp


//---------------------------------------------------------------------------

#include

#include // random и randomize

#include // требуется для использования ключевого слова typeid

#pragma hdrstop


#include "OOPExample.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TfrmOOPExample *frmOOPExample;

//---------------------------------------------------------------------------

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

//---------------------------------------------------------------------------

__fastcall TfrmOOPExample::TfrmOOPExample(TComponent* Owner)

: TForm(Owner)

{

randomize();


// Статически определенные

static CPoint p(100, 100); // точку

static CCircle c(p, 10); // окружность

static CEllipse e(p, 20, 12); // эллипс

static CPoint coords[] = { // и ломаную

CPoint(p.X() - 30, p.Y() - 30),

CPoint(p.X() + 30, p.Y() - 30),