Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

<p id="AutBody_Root713"><strong>Приложение Д</strong></p><p><strong>Реализация графического пользовательского интерфейса</strong></p>

“Когда вы наконец поймете, что делаете,

то все пойдет правильно”

Билл Фэйрбэнк (Bill Fairbank)

В этом приложении представлена реализация обратных вызовов, а также классов Window, Widget и Vector_ref. В главе 16 мы не требовали от читателей знать об указателях и операторах приведения типа, поэтому вынесли подробные объяснения в приложение.

<p id="AutBody_Root714"><strong>Д.1. Реализация обратных вызовов</strong></p>

Обратные вызовы реализованы следующим образом:

void Simple_window::cb_next(Address, Address addr)

// вызов функции Simple_window::next для окна,

// расположенного по адресу addr

{

  reference_to(addr).next;

}

Поскольку вы уже прочитали главу 17, то вам должно быть очевидно, что аргумент Address должен иметь тип void*. И, разумеется, функция reference_to(addr) должна каким-то образом создавать ссылку на объект класса Simple_window из указателя addr, имеющего тип void*. Однако, если у вас нет опыта программирования, то ничто для вас не “очевидно” и не “разумеется”, пока вы не прочтете главу 17, поэтому рассмотрим и использование адресов подробнее.

Как описано в разделе A.17, язык C++ предлагает способ для указания имени типа. Рассмотрим пример.

typedef void* Address; // Address — это синоним типа void*

Это значит, что мы можем использовать имя Address вместо void*. В данном случае, используя имя Address, мы хотим подчеркнуть, что передаем адрес, и скрыть тот факт, что void* — это имя типа указателя на объект, тип которого неизвестен.

Итак, функция cb_next получает указатель типа void* с именем addr в качестве аргумента и — каким-то образом — немедленно преобразовывает его в ссылку Simple_window&:

reference_to(addr)

Функция reference_to является шаблонной (раздел A.13).

templateW& reference_to(Address pw)

// интерпретирует адрес как ссылку на объект класса W

{

  return *static_cast(pw);

}

Здесь мы использовали шаблонную функцию, для того чтобы самостоятельно написать операции, действующие как приведение типа void* к типу Simple_window&. Это приведение типа static_cast описано в разделе 17.8.

Компилятор не имеет возможности проверить наши предположения о том, что аргумент addr ссылается на объект класса Simple_window, но правила языка требуют, чтобы компилятор в этом вопросе доверял программисту. К счастью, мы оказались правы. Об этом свидетельствует от факт, что система FLTK возвращает нам обратно указатель, который мы ей передавали. Поскольку, передавая указатель системе FLTK, мы знали его тип, можно использовать функцию reference_to, чтобы “получить его обратно”. Все это немного запутанно, не проходит проверку и не больше характерно для низкоуровневого программирования.

Получив ссылку на объект класса Simple_window, мы можем использовать ее для вызова функции-члена класса Simple_window. Рассмотрим пример (раздел 16.3).

void Simple_window::cb_next(Address, Address pw)

// вызов функции Simple_window::next для окна,

// расположенного по адресу pw

{

  reference_to(pw).next;

}

Мы использовали довольно сложную функцию обратного вызова cb_next, просто чтобы согласовать типы, необходимые для вызова совершенно обычной функции-члена next.

<p id="AutBody_Root715"><strong>Д.2. Реализация класса Widget</strong></p>

Наш интерфейсный класс 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; }

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT