class="empty-line"/>
Этот код не работает. Все кнопки являются локальными объектами в функции load_disaster_menu, и их связывание с меню не изменяет состояние самого меню. Объяснение этого факта приведено в разделе 18.5.4, а размещение локальных переменных в памяти было проиллюстрировано в разделе 8.5.8. Дело в том, что после возврата управления из функции load_disaster_menu() эти локальные объекты были уничтожены, и меню disasters ссылается на несуществующие (уничтоженные) объекты. Результат неожиданный и неприятный. Устранить эту ошибку можно, используя неименованные объекты, созданные оператором new, а не именованные локальные объекты.
// вспомогательная функция для загрузки кнопки в меню
void load_disaster_menu(Menu& m)
{
Point orig(0,0);
m.attach(new Button(orig,0,0,"flood",cb_flood));
m.attach(new Button(orig,0,0,"fire",cb_fire));
// ...
}
Правильное решение даже проще, чем ошибочный код (впрочем, очень широко распространенный).
Задание
1. Создайте совершенно новый проект, связав его с библиотекой FLTK1. (Установки редактора связей описаны в приложении Г.)
2. Используя средства, описанные в файле Graph_lib, выведите какой-нибудь текст в программе из раздела 16.5 и выполните ее.
3. Модифицируйте программу так, чтобы она использовала всплывающее меню, как описано в разделе 16.7, и выполните ее.
4. Измените программу так, чтобы в ней было второе меню для выбора стиля линий, и выполните ее.
Контрольные вопросы
1. Зачем нужен графический пользовательский интерфейс?
2. Когда нужен текстовый интерфейс?
3. Что такое уровень программного обеспечения?
4. Зачем нужны уровни программного обеспечения?
5. В чем заключается фундаментальная проблема взаимодействия с операционной системой с помощью языка C++?
6. Что такое обратный вызов?
7. Что такое виджет?
8. Как еще называют виджет?
9. Что означает аббревиатура FLTK?
10. Как читается аббревиатура FLTK?
11. О каких еще инструментах графического пользовательского интерфейса вы знаете?
12. Какие системы используют термин виджет, а какие — элемент управления окном?
13. Приведите примеры виджетов.
14. Когда используются окна редактирования для ввода?
15. Какие типы данных могут храниться в окнах редактирования для ввода?
16. Когда используется кнопка?
17. Когда используется меню?
18. Что такое инверсия управления?
19. Опишите основную стратегию отладки программ с графическим пользовательским интерфейсом.
20. Почему отладка программ с графическим пользовательским интерфейсом труднее, чем отладка обычной программы с потоками ввода-вывода?
Термины
Упражнения
1. Создайте класс My_window, похожий на класс Simple_window, за исключением того, что он имеет две кнопки: Next и Quit.
2. Создайте окно (на основе класса My_window) с шахматной доской 4×4. После щелчка на кнопке должно выполняться простое действие, например вывод ее координат в окно редактирования или изменение цвета (пока не будет выполнен другой щелчок на другой кнопке).
3. Разместите объект класса Image поверх объекта класса Button; после щелчка на кнопке переместите оба объекта. Для выбора нового местоположения кнопки с изображением используйте следующий генератор случайных чисел:
int rint(int low, int high)
{ return low+rand()%(high–low); }
Эта функция возвращает случайное целое число в диапазоне [low, high].
4. Создайте меню с пунктами “окружность”, “квадрат”, “равносторонний треугольник” и “шестиугольник”. Создайте окно редактирования (или два окна) для ввода пар координат и разместите фигуру, созданную после щелчка на соответствующей кнопке, в заданной точке. Не применяйте метод “перетащить и отпустить”.
5. Напишите программу, рисующую фигуру по вашему выбору и перемещающую ее в новую точку после щелчка на кнопке Next. Новая точка должна выбираться на основе пары координат, считанной из потока ввода.
6. Создайте “аналоговые часы”, т.е. часы с двигающимися стрелками. Определите время, используя средства операционной системы. Основная часть этого упражнения: найти функции, определяющие время дня и прекращающие выполнение программы на короткий период времени (например, на секунду), а также научиться использовать их по документации. Подсказка: clock(), sleep().
7. Использование приемов из предыдущего упражнения позволяет создать иллюзию полета самолета по экрану. Создайте кнопки Start и Stop.
8. Создайте конвертер валют. Считайте курсы валют из файла в момент запуска программы. Введите сумму в окне ввода и предусмотрите возможность выбора валют для конверсии (например, пару меню).
9. Модифицируйте калькулятор из главы 7 так, чтобы выражение вводилось в окне редактирование, а результат возвращался в окне вывода.
10. Разработайте программу, в которой можно выбрать одну из нескольких функций (например, sin() и log()), введите параметры этих функций и постройте ее график.
Послесловие
Графический пользовательский интерфейс — неисчерпаемая тема. Большая часть этой темы касается стиля и совместимости с существующими системами. Более того, много сложностей возникает при работе с чрезвычайно разнообразными элементами управления окном (например, библиотека графического пользовательского интерфейса предлагает многие десятки альтернативных стилей кнопок), — раздолье для “ботаников”. Однако лишь немногие вопросы из этой области относятся к фундаментальным методам программирования, поэтому мы не будем углубляться в этом направлении. Другие темы, такие как масштабирование, вращение, анимация, трехмерные объекты и так далее, требуют изложения сложных фактов, связанных с графикой и/или математикой, которые мы затрагивать здесь не хотим.
Вы должны знать о том, что большинство систем графического пользовательского интерфейса имеет программу-компоновщик, позволяющую визуально создавать окна, присоединять к ним обратные вызовы и задавать действия кнопок, меню и т.д. Во многих приложениях такие программы-компоновщики позволяют существенно сократить процесс программирования, например обратных вызовов. Однако всегда следует понимать, как будет работать результирующая программа. Иногда сгенерированный код эквивалентен тому, что вы видели в главе. Порой для этого используются более сложные и/или крупные механизмы.
Часть III
Данные и алгоритмы
Глава 17
Векторы и свободная память
“Используйте vector по умолчанию”.
Алекс Степанов (Alex Stepanov)
В этой и четырех следующих главах описываются контейнеры и алгоритмы из стандартной библиотеки языка С++, которую обычно называют STL. Мы рассматриваем основные возможности библиотеки STL и описываем их применение. Кроме того, излагаем ключевые методы проектирования и программирования, использованные при разработке библиотеки STL, а также некоторые низкоуровневые свойства языка, примененные при этом. К этим свойствам относятся указатели, массивы и свободная память. В центре внимания этой и следующих двух глав находятся проектирование и реализация наиболее популярного и полезного контейнера из библиотеки STL: vector.
17.1. Введение
Наиболее полезным контейнером, описанным в стандартной библиотеке языка С++, является класс vector. В векторе хранится последовательность элементов одного