|
Программирование >> Операторы преобразования типа
#lnclLide <vector> #inc1ude <algor1thm> using namespace std: Обьект функции для вычисления среднего арифметического class MeanValue ( private: long num: Счетчик элементов long sum: Сумма всех значений элементов public: Конструктор MeanValue () : num(O). sum(O) { } Вызов функции - обработка очередного элемента последовательности void OperatorO (int elem) ( num++; Увеличение счетчика sum += elem; Прибавление значения Возвращение среднего арифметического double value () { return stat1c cast<double>Csum) / static cast<double>(num); 1nt mainO ( vector<lnt> coll: Вставка элементов от 1 до 8 for (int i=l; i<=8: ++1) { coll.push back(i); Вычисление и вывод среднего арифметического MeanValue mv = for each (coll .beginO. coll.endO. Интервал MeanValueO); Операция cout mean value: mv.valueO endl; Вызов MeanValueO создает объект функции, который подсчитывает количество элементов и вычисляет сумму их значений. Передача этого объекта при вызове for each() обеспечивает его вызов для каждого элемента контейнера соН; MeanValue mv = for each (coll.beginO. coll.endO. MeanValueO); Объект функции, возвращенный алгоритмом for each(), присваивается mv, поэтому после вызова можно запросить информацию о его состоянии в виде mv.value(). В итоге программа выводит следующий результат: mean value: 4.5 Класс MeanValue можно дополнительно усоверщенствовать, определив автоматическое преобразование к типу double. В этом случае среднее арифметическое, вычисленное for each(), можно будет напрямую использовать в программе. Пример такого рода приведен на с. 335. Предикаты и объекты функций предикатом называется функция или объект функции, возвращающий логическое значение (или значение, преобразуемое к bool). Однако не каждая функция, возвращающая логическую величину, является предикатом по правилам STL. Иногда это приводит к весьма странным последствиям. Рассмотрим следующий пример: fo.removeif.срр Unclude <1ostream> Unclude <l1st> Unclude <algor1thm> Iinclude print.hpp using namespace std; class Nth (, Объект функции возвращает true для n-го вызова private: 1nt nth; Номер вызова, для которого следует вернуть true int count: Счетчик вызовов public: Nth (int n) : nth(n). count(O) ( } bool OperatorO (int) { return ++count == nth: int mainO ( list<int> col 1: Вставка элементов со значениями от 1 до 9 for (int i=l; i<=9: ++i) ( coll.push back(i): PRINT ELEMENTS(coll. coll: ): Удаление третьего элемента list<int>::iterator pos: pos = removejf(coll .beginO .col 1 .endO. Интервал Nth(3)): Критерий удаления coll .erase(pos.coll .endO); PRINT ELEMENTS(coll. nth removed: ); Программа определяет объект функции Nth, который возвращает true для каждого п-го вызова. Но если передать этот объект алгоритму removejf(), выполняющему удаление всех элементов, для которых унарный предикат возвращает true (см. с. 371), вас ждет сюрприз: coll: 12 3 4 5 6 7 8 9 nth removed: 12 4 5 7 8 9 Из коллекции удаляются два элемента, третий и шестой. Дело в том, что обычная реализация алгоритма создает внутреннюю копию предиката: template <class ForwIter. class Predlcate> Forwiter std: .remove 1f(ForwIter beg, ForwIter end. Predicate op) beg = f1nd 1f(beg. end. op): lf (beg == end) ( return beg; else ( ForwIter next = beg; return remove copy 1f(++next. end. beg. op); Для поиска первого удаляемого элемента алгоритм использует find if(), но затем для обработки оставшихся элементов используется копия переданного предиката ор. Объект функции Nth возвращается к прежнему состоянию и удаляет третий элемент из оставшихся (то есть шестой элемент коллекции). Такое поведение не является ошибкой. Стандарт не ограничивает внутреннее копирование предиката в алгоритме. Таким образом, для надежной работы алгоритмов стандартной библиотеки С++ не следует передавать объект функции, поведение которого зависит от частоты его копирования или вызова. Иначе говоря, если унарный предикат вызывается с одинаковыми аргументами, то он всегда должен возвращать один и тот же результат. Вызов не должен изменять внутреннее состояние предиката, а копия предиката должна иметь точно такое же состояние, как оригинал. Чтобы состояние предиката не изменялось при вызове функции, оператор () рекомендуется объявлять в виде чконстантной функции. В принципе это странное поведение можно обойти и обеспечить нормальную работу алгоритма даже с такими объектами функций, как Nth, без сниже-
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |