C++. Сборник рецептов - [201]
>load()
и >save()
. Если вам необходимо воспользоваться преимуществами этой возможности, обратитесь к документации Boost.Serialization.В примерах 14.25, 14.26 и 14.27 я использую функцию >boost::serialization::make_nvp
для конструирования пар вида «имя-значение». В Boost.Serialization предусмотрен также макрос >BOOST_SERIALIZATION_NVP
, который позволяет выполнять сериализацию переменной, указывая ее имя. Первый компонент пары будет сконструирован автоматически препроцессором, используя оператор «стрингизации» (stringizing) >#
для преобразования макропараметров в строковые константы.
>// То же самое, что и ar & make_nvp("name_", name_);
>ar & BOOST_SERIALIZATION_NVP(name_);
В этих примерах я использую >make_nvp
вместо >BOOST_SERIALIZATION_NVP
для лучшего контроля имен тегов, чтобы содержимое архива XML легче читалось.
В документации Boost.Serialization рекомендуется объявлять метод >serialize()
как закрытый (>private
) для уменьшения ошибок пользователя, когда добавляется поддержка сериализации в классы, производные от других сериализуемых классов. Для того чтобы библиотека Boost.Serialization могла вызвать метод >serialize()
вашего класса, вам необходимо объявить дружественным класс boost::>serialization::access
.
Наконец второй параметр метода >serialize()
в примерах 14.25 и 14.26 относится к той части Boost.Serialization, которая поддерживает управление версиями классов (class versioning). Когда объект определенного класса первый раз сохраняется в архиве, вместе с ним сохраняется также его версия; когда выполняется десериализация экземпляра класса. Boost.Serialization передает сохраненную версию методу >serialize
в качестве второго аргумента. Эта информация может использоваться для специализации десериализации; например, >serialize
мог бы загружать переменную-член только в том случае, если записанная в архив версия класса, по крайней мере, не меньше версии класса, первым объявившим эту переменную. По умолчанию класс имеет версию 0. Для задания версии класса вызовите макрос >BOOST_CLASS_VERSION
, который определен в заголовочном файле boost/serialization/version.hpp, передавая в качестве аргументов имя и версию класса.
Глава 15
Разные функции
15.0. Введение
В этой главе рассматриваются некоторые аспекты C++, которые плохо вписываются в тематику любой другой главы: указатели функций и членов, константные переменные и функции- члены, независимые операторы (т.е. не члены класса) и несколько других тем.
15.1. Применение указателей функций для их обратного вызова
Планируется использование некоторой функции >func1
, которая на этапе выполнения должна вызывать другую функцию >func2
. Однако по той или иной причине нельзя внутри функции >func1
жестко закодировать имя функции >func2
. Возможно, имя функции >func2
неизвестно на этапе компиляции, или >func1
относится к программному интерфейсу независимого разработчика, и она не может быть изменена и перекомпилирована В любом случае вам придется воспользоваться функцией обратного вызова (callback function).
При использовании указанных выше функций объявите >func1
с указателем на функцию в качестве своего аргумента и передайте ей адрес >func2
на этапе выполнения. Используйте >typedef
, чтобы программа легче читалась и отлаживалась. Пример 15.1 показывает, как можно реализовать функцию обратного вызова, используя указатель на функцию.
Пример 15.1. Функция обратного вызова
>#include
>// Пример функции обратного вызова
>bool updateProgress(int pct) {
> std::cout << pct << "% complete...\n";
> return(true);
>}
>// Этот typedef делает программный код более понятным
>typedef bool (*FuncPtrBoolInt)(int);
>// Функция, которая выполняется достаточно длительное время
>void longOperation(FuncPtrBoolInt f) {
> for (long l=0; l < 100000000; l++)
> if (l % 10000000 == 0)
> f(l/1000000);
>}
>int main() {
> longOperation(updateProgress); // нормально
>}
В ситуации, которая показана в примере 15.1, применение указателя на функцию является хорошим решением, если >UpdateProgress
и >longOperation
ничего не должны знать друг о друге. Например, функцию, которая обновляет индикатор состояния процесса в диалоговом окне пользовательского интерфейса (user interface — UI), в окне консольного режима или где-то еще, не заботит контекст, в котором она вызывается. Аналогично функция >longOperation
может быть частью некоторого программного интерфейса загрузки данных, которого не заботит место вызова: из графического UI, из окна консольного режима или из фонового процесса.
Сначала потребуется определить сигнатуру функции, которую вы планируете вызывать, и создать для нее >typedef
. Оператор >typedef
— ваш помощник в тех случаях, когда приходится иметь дело с указателями функций, потому что они имеют не очень привлекательный синтаксис. Рассмотрим, как обычно объявляется такой указатель на примере переменной >f
, которая содержит адрес функции, принимающей единственный аргумент целого типа и возвращающей значения типа >boolean
. Это может выглядеть следующим образом
>bool (*f)(int); // f - имя переменной
Вы можете справедливо возразить, что здесь нет ничего особенного и я просто излишне драматизирую ситуацию. Но что вы скажете, если требуется определить вектор
![Изучаем Java EE 7](/storage/book-covers/e0/e0ee9b7e3e4f168a93df98d7e47d66089eac3652.jpg)
Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)
![Геймдизайн. Рецепты успеха лучших компьютерных игр от Super Mario и Doom до Assassin’s Creed и дальше](/storage/book-covers/d0/d0fc13172d4310c9da7b10ba57a3fcb2e3d9f10d.jpg)
Что такое ГЕЙМДИЗАЙН? Это не код, графика или звук. Это не создание персонажей или раскрашивание игрового поля. Геймдизайн – это симулятор мечты, набор правил, благодаря которым игра оживает. Как создать игру, которую полюбят, от которой не смогут оторваться? Знаменитый геймдизайнер Тайнан Сильвестр на примере кейсов из самых популярных игр рассказывает как объединить эмоции и впечатления, игровую механику и мотивацию игроков. Познакомитесь с принципами дизайна, которыми пользуются ведущие студии мира! Создайте игровую механику, вызывающую эмоции и обеспечивающую разнообразие.
![Обработка событий в С++](/build/oblozhka.dc6e36b8.jpg)
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
![MFC и OpenGL](/build/oblozhka.dc6e36b8.jpg)
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
![Симуляция частичной специализации](/storage/book-covers/7e/7e33d937f206a76edb7f45006e896cc191605df5.jpg)
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
![Питон — модули, пакеты, классы, экземпляры](/build/oblozhka.dc6e36b8.jpg)
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.