Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++ Страуструп.doc
Скачиваний:
4
Добавлен:
18.04.2019
Размер:
2.72 Mб
Скачать

6.4.2 Библиотека фигур

Начнем с определения общего понятия фигуры. Определение должно

быть таким, чтобы им можно было воспользоваться (как базовым классом

shape) в разных классах, представляющих все конкретные фигуры

(окружности, квадраты и т.д.). Оно также должно позволять работать

со всякой фигурой исключительно с помощью интерфейса, определяемого

классом shape:

struct shape {

static shape* list;

shape* next;

shape() { next = list; list = this; }

virtual point north() const = 0;

virtual point south() const = 0;

virtual point east() const = 0;

virtual point west() const = 0;

virtual point neast() const = 0;

virtual point seast() const = 0;

virtual point nwest() const = 0;

virtual point swest() const = 0;

virtual void draw() = 0;

virtual void move(int, int) = 0;

};

Фигуры помещаются на экран функцией draw(), а движутся по нему

с помощью move(). Фигуры можно помещать относительно друг друга,

используя понятие точек контакта. Для обозначения точек контакта

используются названия сторон света в компасе: north - север, ... ,

neast - северо-восток, ... , swest - юго-запад. Класс каждой

конкретной фигуры сам определяет смысл этих точек и определяет,

как рисовать фигуру. Конструктор shape::shape() добавляет

фигуру к списку фигур shape::list. Для построения этого списка

используется член next, входящий в каждый объект shape. Поскольку

нет смысла в объектах типа общей фигуры, класс shape определен как

абстрактный класс.

Для задания отрезка прямой нужно указать две точки или точку

и целое. В последнем случае отрезок будет горизонтальным, а целое

задает его длину. Знак целого показывает, где должна находиться заданная

точка относительно конечной точки, т.е. слева или справа от нее:

class line : public shape {

/*

отрезок прямой ["w", "e" ]

north() определяет точку - `` выше центра отрезка и

так далеко на север, как самая его северная точка''

*/

point w, e;

public:

point north() const

{ return point((w.x+e.x)/2,e.y<w.y?w.y:e:y); }

point south() const

{ return point((w.x+e.x)/2,e.y<w.y?e.y:w.y); }

point east() const;

point west() const;

point neast() const;

point seast() const;

point nwest() const;

point swest() const;

void move(int a, int b)

{ w.x +=a; w.y +=b; e.x +=a; e.y +=b; }

void draw() { put_line(w,e); }

line(point a, point b) { w = a; e = b; }

line(point a, int l) { w = point(a.x+l-1,a.y); e = a; }

};

Аналогично определяется прямоугольник:

class rectangle : public shape {

/* nw ------ n ----- ne

| |

| |

w c e

| |

| |

sw ------ s ----- se

*/

point sw, ne;

public:

point north() const { return point((sw.x+ne.x)/2,ne.y); }

point south() const { return point((sw.x+ne.x)/2,sw.y); }

point east() const;

point west() const;

point neast() const { return ne; }

point seast() const;

point nwest() const;

point swest() const { return sw; }

void move(int a, int b)

{ sw.x+=a; sw.y+=b; ne.x+=a; ne.y+=b; }

void draw();

rectangle(point,point);

};

Прямоугольник строится по двум точкам. Конструктор усложняется, так

как необходимо выяснять относительное положение этих точек:

rectangle::rectangle(point a, point b)

{

if (a.x <= b.x) {

if (a.y <= b.y) {

sw = a;

ne = b;

}

else {

sw = point(a.x,b.y);

ne = point(b.x,a.y);

}

}

else {

if (a.y <= b.y) {

sw = point(b.x,a.y);

ne = point(a.x,b.y);

}

else {

sw = b;

ne = a;

}

}

}

Чтобы нарисовать прямоугольник, надо нарисовать четыре отрезка:

void rectangle::draw()

{

point nw(sw.x,ne.y);

point se(ne.x,sw.y);

put_line(nw,ne);

put_line(ne,se);

put_line(se,sw);

put_line(sw,nw);

}

В библиотеке фигур есть определения фигур и функции для работы

с ними:

void shape_refresh(); // нарисовать все фигуры

void stack(shape* p, const shape* q); // поместить p над q

Функция обновления фигур нужна, чтобы работать с нашим примитивным

представлением экрана; она просто заново рисует все фигуры. Отметим,

что эта функция не имеет понятия, какие фигуры она рисует:

void shape_refresh()

{

screen_clear();

for (shape* p = shape::list; p; p=p->next) p->draw();

screen_refresh();

}

Наконец, есть одна действительно сервисная функция, которая рисует

одну фигуру над другой. Для этого она определяет юг (south()) одной

фигуры как раз над севером (north()) другой:

void stack(shape* p, const shape* q) // поместить p над q

{

point n = q->north();

point s = p->south();

p->move(n.x-s.x,n.y-s.y+1);

}

Представим теперь, что эта библиотека является собственностью

некоторой фирмы, продающей программы, и, что она продает только

заголовочный файл с определениями фигур и оттранслированные

определения функций. Все равно вы сможете определить новые фигуры,

воспользовавшись для этого купленными вами функциями.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]