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 - имя переменной

Вы можете справедливо возразить, что здесь нет ничего особенного и я просто излишне драматизирую ситуацию. Но что вы скажете, если требуется определить вектор


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.