Г. Шилдт - Полный справочник по C++ (1109478), страница 100
Текст из файла (страница 100)
на экран слсдуюшис результаты. Исходное содержимое списка ча1в: 10 20 30 40 50 60 70 80 90 Измененное содержимое списка ча1я: 3.33333 6.66667 10 13.3333 16.6667 20 23.3333 26.6667 30 В данном случае бинарный функтор алчЫев (] делит элементы первой послсловательности на соотвстствуюшие элементы второй послсловатсльности. Таким образом, функтор»тлчл()ее О получает свои аргументы в слсдуюшсм порядке. $ д?чЫея (/)гзг, тесов)); Этот порялок можно обобшить.
Независимо от применяемого бинарного функтора, его аргументы всегда перечисляются в указанном порядке /йзг, засол»1 Создание функтора Кроме встроенных функторов, можно созлавать и применять свои собственныс функторы. Для этого достаточно создать класс, в котором перегружается операторная функция оретаеот(). Однако, чтобы достичь большей гибкости, для создания функторов следует использовать паин из слелуюших базовых классов, определенных в классе ВТ1 севр1асе <с1аяя Атдшпеп», с1авв леви1?> встпсс ипату липс?ьоп суре»)еб Атдшпеп».
атдшпепс ?уре; суре»)еб иеви1? теви1» туре; ); ?шпр1асе <с1аяв Атдшаеп?1, с1авв Атдшпеп»2, с1авв кеяи1?> ястцсс Ь1пату бппс?ьоп ( суре»)еб Атдтдпеп»1 б?тв? атдшпепс ?урез Суре»)ей Атдшпеп»2 весопе) атдшпеп» туре; Суре»)еб невп1» теви1» суре» Глава 24. Введение в стандартную библиотеку шаблонов Эти шаблонные классы конкретизируют имена обобшенных типов данных, используемых функтором.
Они весьма удобны, и практически всегда применяются для создания функторов. Слсдуюшая программа демонстрирует обобщенный функтор. Она преобразует функцию хес1рхоса1(), использованную при описании алгоритма ххапяхохвО, в функтор. // Создание функтора хесьрхоса1. ()1пс1и<)е <1ояххеаза> Фтпс1и<)е <11яс> $1пс1ибе <Випсхьопа1> Фтпс1и<)е <а1дох1х)иа> ияьпд патеярасе ях<)," // Простой функтор.
с1аяя хесьрхоса1: плаху йипсх1оп<йоиЫе, доиЫе> риЫ1с: хеяи1х суре орехахох()(ахдитепс суре 1) ( хесихп (хеяи1с суре) 1.0/1; // Возярамаем обратное число. ) ьпх ма1п!) ) ьяс<боиЫе> ча1я; ьпс 1; // Заносим значения я список. Вох(1=1; 1<10; 1++) ча1я.риян Ьас)с((<)оиЫе)1); соис « ".исходное содержимое списка ча1ягхп"у 11яс<боиые>::1хехасох р = ча1я.Ьед1л(); мЫ1е(р )= ча1я.епг)()) [ соис « *р « р++ ' соих « епд1; // Применение функтора хесьрхоса1.
р = схапяйохе(ча1я.Ьедхп О, ча1я.епб(), ча1я.Ьедьп(), хесьрхоса1()); // Вызов функтора. соих « "измененное содержимое списка ча1я> хп"у р = ча1я.Ьедьп(); мЬ11е(р .= ча1я.епб()) соис « *р « р++; ) хесихп 0; ) Обратите внимание на два важных аспекта, связанных с функтором хесдрхоса1(). Во-первых, он наследует свойства базового класса ипату Яииссзап, а также предоставляет доступ к типам ахдимепс суре и хееи1с суре.
Во-вторых, этот фактор определяет операторную функцию орехаеохО, возврашаюшую обратное значение аргумента. Как правило, чтобы создать функтор, достаточно создать класс, производный от одного из базовых классов„указанных выше, и перегрузить оператор () . Это действительно просто. Часть П. Язык С++ Применение редакторов связей При вызове бинарного функтора олин из его аргументов можно связать с конкретным значением.
Во многих ситуациях это свойство оказывается довольно полезным. Допустим, что из последовательное~и требуется удалить все элементы, превышающие определенное значение, например, число 8. Для этого необходимо иметь возможность связывазь число 8 с правым операндом функтора вхеаеех().
Иначе говоря, желательно, чтобы функтор яхеекехо мог выполнять сравнение Вча1 > Б лля кажлого элемента послеловательности. В библиотеке БТ). сушествует лгеханизм, позволяюший это делать. Он называется редактором связей (Ь)пйег). Сушествуют лва редактора связей — Ьхпй2пй() и Ъвпй1вс(), имеюшие слелуюший вид. Ъхпй1вх(ЬЬ(Галс аЬ), ва(ие) Ъьпй2ах (Ьв())в!с аЬз, ва!ие) Здесь параметр Ылгилс оЬ! является бинарным функтором. Редактор связей ъзпйзвс() возврашает унарный функтор, у которого левый операнд функтора Ыфйпс оЬЗ связан со значением та)ие. Редактор связей Ьвпй2вх() возвращает унарный функтор, у которого со значением та)ие связан правый операнд функтора ЫлДлс оЬ!. Этот релактор связей используется чаше.
В любом случае результатом работы редактора связей является унарный функтор, связанный с определенным значением. Продемонстрируем работу редактора связей на примере алгоритма хеакпге хс(). Он удаляет элементы из последовательности, анализируя результат преликата. Его прототип имеет слелующий вил. севр1ахе <с1авв Рох1хех, с1авв цпрхей> Рохтхех хототе Ьс(вохтхех пап, Рохтхех евА ппрхей гвас); Алгоритм удаляет элементы из диапазона, определенного итераторами згагг и еи(, если унарный предикат, заданный параметром ~илс, являешься истинным.
Алгоритм возврашает указатель на конец новой последовательности, образованной вследствие улаления элементов. Следуюшая программа удаляв~ из последовательности все элементы, превышаюшие число 8. Поскольку предикат, необходимый редактору связей хевюве хх(), является унарным, мы не можем просто вызнаешь бинарный функтор дхеехех(). Вместо этого слелует связать число 8 со вторым аргументом функтора яхеееех(), используя редактор связей Ъзпй2пй() . г/ Демонстрация педактора связей Ъ1пй2пй() ()ьпс1пйе <1овххеап» втпс1пйе <1хвс> Лтпс1ийе <хппсх1опа1> Ььпс1ийе <а10охйх)иа> пв1пд пазаеврасе вхй! ьпх гсатп() 11вс<ьпс> 1всг 1хвх<хпс>::ххехахох р, епйр; Ьпх хох(1=1! х < 20; 1++) 1вх.рпвп Ъасй(1); Глава 24.
Введение в стандартную библиотеку шаблонов соус « "Исходная последовательностьзтп"з р = 1вс.Ьедъп[)з ьиз.1е(р з= 1вс.епс)()) ( сост « *р « р.з- е; ) сосс «епй1з епйр = гетоуе 18(1вс.ЬедгпО, 1вг.епй(), Ьз ой2пй(дгеасет<зпс> О, 8)); ссас « "Результирующая послсловательностьзтл"з р = 1вс.Ьедтп()з иЬ11е(р з= епйр) ( соус « р « рве; гесптп Оз ) Результат работы этой программы приведен ниже. | Исходная гослеловательносты 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1б 17 18 19 Результирующая последовательность: 12 345 б78 Поэкспериментируите с этой программой, применяя разные Функторы и редакторы связей. Вы убелитесь, насколько рслакгоры связей увеличивают мощь библиотеки БТ1 И последнее: в библиотеке есть объек~, тесно связанный с редактором связей.
Он называется инаеразарам (пека(ог) и возвращает отрицание (т.е. дополнение) предиката. Его общин вид приведен ниже. пог1 ( няаге )зге)(еа(е) з пос2 (8(лагу ргеет(еа)е) з Например, если полставить строку егк)р = тещоуе 18(1вС.Ьедйп(), 1вг.елй() „ пос1(Ь1пй2пй(дтеасег<1пс>(), 8) ) ) ) в предыдущую программу, она удалит нз последовательности 1ве все элементы, не превышающие число 8. ~)'."'"'."'': Класс 81ппя Клк известно, язык С++ не предусматривает встроенного типа лля строк. Для рабогы с ними существует две возможности. Во-первых, можно использовать традиционный массив символов, завершающийся нулевым байтом, с которым лзы уже хорошо знакомы.
Инопш этот массив назьзвают С'-сазракай. Во-вторых, можно создать объект класса ветдпд. Рассмотрим этот способ подробнее. Фактически класс встдпд является специализацией более общего шаблонного класса ьавзе ветдпд. На самом деле класс ьввзс встдюд имеет лве специализации: класс векйпд, поддерживающий 8-битовые строки, и класс ивеюйпд, пред- Часть (!. Язык С++ назначенный лля работы со строками расширенных символов. Поскольку 8- битовые строки до сих пор широко используются в программировании, мы рассмотрим лишь класс всв1пд.
Пре)кде чем перейти к изучению класса всвзпд, следует разобраться, почему его включили в библиотеку языка С++. Стандартные классы обычна не являются частью языка С++. Каждое новшество языка сопровождается длительными и напряженнызви дебатами. Поскольку язык С++ уже содержал средства для работы с массивами символов, завершающихся нулевым байтом, класс вткдпд, на первый взгляд, выглядит исключением из этого правила. Однако зто неверно, поскольку к строкам, завершающимся нулевым байтом, нельзя применить ни один стандартный оператор языка С++.
Такие строки не могут быть частью обычных выражений. Рассмо~рим, например, следующий фрагмент. сЬах в1 [80), в2 [80), вЗ [80) р в1 = "Аль$а" ) // Нельзя! в2 = "Бета"; // Нельзя! вЗ = в1 я в2," // Ошибка. и так нельзя! Как следует из комментариев, в языке С++ невозможно ни присвоить массиву символов новое значение, используя оператор присваивания (за исключением инициализации), ни применить оператор "+*' для конкатенации двух строк. Эти операции следует записать, используя библиотечные функции.