константы.
// То же самое, что и 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, которая поддерживает serialize
в качестве второго аргумента. Эта информация может использоваться для специализации десериализации; например, serialize
мог бы загружать переменную-член только в том случае, если записанная в архив версия класса, по крайней мере, не меньше версии класса, первым объявившим эту переменную. По умолчанию класс имеет версию 0. Для задания версии класса вызовите макрос BOOST_CLASS_VERSION
, который определен в заголовочном файле
Глава 15
Разные функции
15.0. Введение
В этой главе рассматриваются некоторые аспекты C++, которые плохо вписываются в тематику любой другой главы: указатели функций и членов, константные переменные и функции- члены, независимые операторы (т.е. не члены класса) и несколько других тем.
15.1. Применение указателей функций для их обратного вызова
Планируется использование некоторой функции func1
, которая на этапе выполнения должна вызывать другую функцию func2
. Однако по той или иной причине нельзя внутри функции func1
жестко закодировать имя функции func2
. Возможно, имя функции func2
неизвестно на этапе компиляции, или func1
относится к программному интерфейсу независимого разработчика, и она не может быть изменена и перекомпилирована В любом случае вам придется воспользоваться функцией
При использовании указанных выше функций объявите func1
с указателем на функцию в качестве своего аргумента и передайте ей адрес func2
на этапе выполнения. Используйте typedef
, чтобы программа легче читалась и отлаживалась. Пример 15.1 показывает, как можно реализовать функцию обратного вызова, используя указатель на функцию.
#include <iostream>
// Пример функции обратного вызова
bool updateProgress(int pct) {
std::cout << pct << '% complete...
';
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 - имя переменной
Вы можете справедливо возразить, что здесь нет ничего особенного и я просто излишне драматизирую ситуацию. Но что вы скажете, если требуется определить вектор vector
таких указателей?
vector<bool (*)(int)> vf;
Или их массив?
bool (*af[10])(int);
Форма представления указателей на функции отличается от обычных переменных С++, которые обычно задаются в виде (квалифицированного) имени типа, за которым идет имя переменной. Поэтому они