Шрифт:
Интервал:
Закладка:
void Shape::set_point(int i, Point p) // не используется
{
points[i] = p;
}
Point Shape::point(int i) const
{
return points[i];
}
int Shape::number_of_points() const
{
return points.size();
}
В производном классе эти функции используются так:
void Lines::draw_lines() const
// рисует линии, соединяющие пары точек
{
for (int i=1; i<number_of_points(); i+=2)
fl_line(point(i–1).x,point(i–1).y,point(i).x,point(i).y);
}

Решения, касающиеся управления доступом, очень важны. Теперь мы могли бы создать почти минимальную версию класса Shape.
struct Shape { // слишком простое определение — не используется
Shape();
void draw() const; // работает с цветом и вызывает функцию
// draw_lines
virtual void draw_lines() const; // рисует линии
virtual void move(int dx, int dy); // перемещает фигуры +=dx
// и +=dy
vector<Point> points; // не используется всеми фигурами
Color lcolor;
Line_style ls;
Color fcolor;
}

Fl_Color lcolor;
int line_style;
Оказывается, это очень ограничивает наши возможности (стиль линии, задаваемый переменной типа int, не позволяет элегантно задавать ширину линии, а класс Fl_Color не предусматривает невидимые линии) и приводит к довольно запутанному коду. Если бы эти две переменные были открытыми и использовались в пользовательской программе, то мы могли бы улучшить интерфейсную библиотеку только за счет взлома этого кода (поскольку в нем упоминаются имена lcolor и line_style).

14.2.3. Рисование фигур
Мы описали почти все, кроме ядра класса Shape.
void draw() const; // работает с цветом и вызывает функцию
// draw_lines
virtual void draw_lines() const; // рисует линии
Основная задача класса Shape — рисовать фигуры. Мы не можем удалить из класса Shape все остальные функции и оставить его вообще без данных о нем самом, не нанеся вреда нашей основной концепции (см. раздел 14.4); рисование — это главная задача класса Shape. Он выполняет ее с помощью библиотеки FLTK и операционной системы, но с точки зрения пользователя он выполнят только две функции.
• Функция draw() интерпретирует стиль и цвет, а затем вызывает функцию draw_lines().
• Функция draw_lines() подсвечивает пиксели на экране.
Функция draw() не использует никаких новаторских методов. Она просто вызывает функции библиотеки FLTK, чтобы задать цвет и стиль фигуры, вызывает функцию draw_lines(), чтобы выполнить реальное рисование на экране, а затем пытается восстановить цвет и фигуру, заданные до ее вызова.
void Shape::draw() const
{
Fl_Color oldc = fl_color();
// универсального способа идентифицировать текущий стиль
// не существует
fl_color(lcolor.as_int()); // задаем цвет
fl_line_style(ls.style(),ls.width()); // задаем стиль
draw_lines();
fl_color(oldc); // восстанавливаем цвет (предыдущий)
fl_line_style(0); // восстанавливаем стиль линии (заданный
// по умолчанию)
}


Рассмотрим теперь, как организовать работу с функцией draw_lines(). Если немного подумать, то можно прийти к выводу, что функции-члену класса Shape было бы трудно рисовать все, что необходимо для создания любой разновидности фигуры. Для этого пришлось бы хранить в объекте класса Shape каждый пиксель каждой фигуры. Если мы используем вектор vector<Point>, то вынуждены хранить огромное количество точек. И что еще хуже, экран (т.е. устройство для вывода графических изображений) лучше “знает”, как это делать.

struct Shape {
// ...
virtual void