Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КРАТКИЙ ОБЗОР С.doc
Скачиваний:
1
Добавлен:
26.10.2018
Размер:
2.11 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);       }       Представим теперь, что эта библиотека является собственностью       некоторой фирмы, продающей программы, и, что она продает только       заголовочный файл с определениями фигур и оттранслированные       определения функций. Все равно вы сможете определить новые фигуры,       воспользовавшись для этого купленными вами функциями.