Шрифт:
Получив ссылку на объект класса
Simple_window
, мы можем использовать ее для вызова функции-члена класса Simple_window
. Рассмотрим пример (раздел 16.3).
void Simple_window::cb_next(Address, Address pw)
// вызов функции Simple_window::next для окна,
// расположенного по адресу pw
{
reference_to<Simple_window>(pw).next;
}
Мы использовали довольно сложную функцию обратного вызова
cb_next
, просто чтобы согласовать типы, необходимые для вызова совершенно обычной функции-члена next
. Д.2. Реализация класса Widget
Наш интерфейсный класс
Widget
выглядит следующим образом.
class Widget {
// Класс Widget — это дескриптор класса Fl_widget,
// а не сам класс Fl_widget;
// мы пытаемся не смешивать наши интерфейсные классы с FLTK
public:
Widget(Point xy, int w, int h, const string& s, Callback cb)
:loc(xy), width(w), height(h), label(s), do_it(cb)
{ }
virtual ~Widget { } // деструктор
virtual void move(int dx,int dy)
{ hide; pw–>position(loc.x+=dx, loc.y+=dy); show; }
virtual void hide { pw–>hide; }
virtual void show { pw–>show; }
virtual void attach(Window&) = 0; // каждый объект класса
// Widget определяет хотя бы
// одно действие над окном
Point loc;
int width;
int height;
string label;
Callback do_it;
protected:
Window* own; // каждый объект класса Widget
// принадлежит объекту классу Window
Fl_Widget* pw; // каждый объект класса Widget о "своем"
// классе Fl_Widget
};
Обратите внимание на то, что наш класс
Widget
следит за “своим” компонентом библиотеки FLTK и классом Window
, с которыми он связан. Кроме того, отметьте, что для этого нам необходимы указатели, поскольку объект класса Widget
на протяжении времени своего существования может быть связан с разными объектами класса Window
. Ссылки или именованного объекта для этого недостаточно. (Объясните почему?) Объект класса
Widget
имеет местоположение (loc
), прямоугольную форму (width
и height
), а также сметку (label
. Интересно, что он также имеет функцию обратного вызова (do_it
), т.е. связывает образ объекта класса Widget
на экране с фрагментом своего кода. Смысл операций move
, show
, hide
и attach
должен быть очевидным. Класс
Widget
выглядит незаконченным. Он спроектирован как класс реализации, который пользователи не должны видеть слишком часто. Его стоит переделать. Мы подозреваем, что все эти открытые члены и “очевидные” операции содержат подводные камни. Класс
Widget
имеет виртуальную функцию и может быть использован как базовый класс, поэтому в нем предусмотрен виртуальный деструктор (см. раздел 17.5.2). Д.3. Реализация класса Window
Когда следует использовать указатели, а когда ссылки? Мы обсудили этот общий вопрос в разделе 8.5.6. Здесь мы лишь отметим, что некоторые программисты любят указатели и что нам нужны указатели, когда мы хотим сослаться на разные объекты в разные моменты времени.
До сих пор мы скрывали главный класс в нашей графической библиотеке — класс
Window
. Основная причина этого заключалась в том, что он использует указатели, а его реализация с помощью библиотеки FLTK опирается на использование свободной памяти. Вот как описан этот класса в заголовочном файле Window.h
.
class Window : public Fl_Window {
public:
// позволяет системе выбрать место в памяти: