- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
Система графического пользовательского интерфейса (и операционная система) может использоваться программами, написанными на разных языках, но они не могут навязывать всем пользователям стиль языка С++. В частности, ей ничего не известно о наших классах Simple_window и Button. Фактически она вообще ничего не знает о классах и их членах. Тип, требуемый для обратного вызова функции, выбирается так, чтобы его можно было использовать на самых низких уровнях программирования, включая язык C и ассемблер. Функция обратного вызова не возвращает значений и принимает в качестве аргументов два адреса. Мы можем объявить функцию-член так, чтобы она подчинялась этим требованиям.
static void cb_next(Address, Address); // обратный вызов для
// next_button
Здесь ключевое слово static гарантирует, что функция cb_next() может быть вызвана как обычная функция, т.е. не как функция-член, вызываемая через конкретный объект. Если бы функцию-член могла вызывать сама операционная система, было бы намного лучше. Однако интерфейс обратного вызова нужен для программ, написанных на многих языках, поэтому мы используем статическую функцию-член. Аргументы Address указывают на то, что функция cb_next() получает аргументы, имеющие адреса “где-то в памяти”. Ссылки, существующие в языке C++, во многих языках неизвестны, поэтому мы не можем их использовать. Компилятор не знает, какие типы имеют эти аргументы, расположенные “где-то”. Здесь мы снижаемся на уровень аппаратного обеспечения и не можем использовать обычные средства языка. Система вызовет функцию обратного вызова, первый аргумент которой должен представлять собой адрес некоторого элемента графического пользовательского интерфейса (объекта класса Widget), для которого был сделан обратный вызов. Мы не хотим использовать этот первый аргумент, поэтому его имя нам не нужно. Второй аргумент — это адрес окна, содержащего данный объект класса Widget; для функции cb_next() аргументом является объект класса Simple_window.
Эту информацию можно использовать следующим образом:
void Simple_window::cb_next(Address,Address pw)
// вызов Simple_window::next() для окна, расположенного по адресу pw
{
reference_to<Simple_window>(pw).next();
}
Вызов функции reference_to<Simple_window>(pw) сообщает компьютеру, что адрес, хранящийся в переменной pw, должен интерпретироваться как адрес объекта класса Simple_window; иначе говоря, мы можем использовать значение reference_to<Simple_window>(pw) как ссылку на объект класса Simple_window. В главах 17-18 мы еще вернемся к вопросам адресации памяти. Определение функции reference_to (кстати, совершенно тривиальное) мы покажем в разделе Д.1. А пока просто рады наконец получить ссылку на наш объект класса Simple_window и непосредственный доступ к нашим данным и функциям, которые собирались использовать. Теперь поскорее выходим из этого системно-зависимого кода, вызывая нашу функцию-член next().
Мы могли бы привести весь код, который следовало бы выполнить в функции cb_next(), но мы, как и большинство хороших программистов, разрабатывающих графические пользовательские интерфейсы, предпочитаем отделять запутанный низкоуровневый код от нашего превосходного пользовательского кода, поэтому решили обрабатывать обратный вызов с помощью двух функций.
• Функция cb_next() превращает системные соглашения об обратных вызовах в вызов обычной функции-члена next().
• Функция next() делает то, что мы хотели (ничего не зная о запутанном механизме обратного вызова).
Мы используем здесь две функции, руководствуясь общим принципом, гласящим: каждая функция должна выполнять отдельное логическое действие, т.е. функция cb_next() скрывает низкоуровневую системно-зависимую часть программы, а функция next() выполняет требуемое действие. В ситуациях, когда необходим обратный вызов (из системы) в одном из окон, мы всегда определяем пару таких функций; например, см. разделы 16.5–16.7. Перед тем как идти дальше, повторим сказанное.
• Мы определяем наш объект класса Simple_window.
• Конструктор класса Simple_window регистрирует свою кнопку next_button в системе графического пользовательского интерфейса.
• Когда пользователь щелкает на изображении объекта next_button на экране, графический пользовательский интерфейс вызывает функцию cb_next().
• Функция cb_next() преобразует низкоуровневую информацию системы в вызов нашей функции-члена next() для нашего окна.
• После щелчка на кнопке функция next() выполняет требуемое действие.
Это довольно сложный способ вызвать функцию. Однако помните, что мы работаем с основным механизмом, обеспечивающим взаимодействие мыши (или другого устройства) с программой. В частности, следует иметь в виду следующие обстоятельства.
• Как правило, на компьютере одновременно выполняется много программ.
• Программа создается намного позже операционной системы.
• Программа создается намного позже библиотеки графического пользовательского интерфейса.
• Программа может быть написана на языке, отличающемся от того, который используется в операционной системе.
• Описанный метод охватывает все виды взаимодействий (а не только щелчок на кнопке).
• Окно может иметь много кнопок, а программа может иметь много окон.
Однако, поняв, как вызывается функция next(), мы фактически поймем, как обрабатывается каждое действие в программе, имеющей графический пользовательский интерфейс.
16.3.2. Цикл ожидания
Итак, что должна делать функция next() класса Simple_window после каждого щелчка на кнопке в данном (простейшем) случае? В принципе мы хотели бы, чтобы эта операция останавливала выполнение нашей программы в некоторой точке, давая возможность увидеть, что было сделано к этому моменту. Кроме того, мы хотим, чтобы функция next() возобновляла работу нашей программы после паузы.
// создаем и/или манипулируем некоторыми объектами, изображаем
// их в окне
win.wait_for_button(); // работа программы возобновляется с этой
// точки
// создаем и/или манипулируем некоторыми объектами
На самом деле это просто. Сначала определим функцию wait_for_button().
void Simple_window::wait_for_button()
// модифицированный цикл событий:
// обрабатываем все события (по умолчанию),
// выходим из цикла, когда переменная button_pushed становится
// true
// это позволяет рисовать без изменения направления потока
// управления
{
while (!button_pushed) Fl::wait();
button_pushed = false;
Fl::redraw();
}
Как и большинство систем графического интерфейса, библиотека FLTK содержит функцию, приостанавливающую работу программы, пока не произойдет какое-то событие. Версия этой функции в библиотеке FLTK называется wait(). На самом деле функция wait() делает много полезных действий, чтобы наша программа могла

