8
|
elementType operator () (const elementType&
|
eleml,
|
9
|
const elementType&
|
elem2)
|
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
return (eleml * elem2);
}
};
int main ()
{
using namespace std;
Создание двух векторов целых чисел по 10 элементов каждый vector vecMultiplicand, vecMultiplier;
Вставить примеры значений от 0 до 9
for (int nCountl = 0; nCountl < 10; ++ nCountl)
vecMultiplicand.push_back (nCountl);
// Вставить примеры значений от 100 до 109
for (int nCount2 = 100; nCount2 < 110; ++ nCount2)
vecMultiplier.push_back (nCount2);
Третий контейнер содержит результат умножения vector vecResult;
Создать пространство для результата умножения vecResult.resize (10);
494
|
ЗАНЯТИЕ 21. Понятие объектов функций
|
|
|
|
35
|
transform ( vecMultiplicand.begin (),
|
//
|
диапазон
|
множителей
|
36
|
vecMultiplicand.end
|
(),
|
//
|
конец диапазона
|
37
|
vecMultiplier.begin
|
(),
|
//
|
значения
|
множителей
|
vecResult.begin (), // диапазон, содержащий результат
Multiply () ); // умножающая функция
40
41 cout « "The contents of the first vector are: " « endl;
for (size_t nlndexl = 0; nlndexl < vecMultiplicand.size ();
nlndexl)
43 cout « vecMultiplicand [nlndexl] « ’
cout << endl;
46 cout « "The contents of the second vector are: " « endl;
for (size_t nlndex2 = 0; nlndex2 < vecMultiplier.size (); ++nlndex2)
cout << vecMultiplier [nlndex2] « ' ';
cout << endl << endl;
50
cout << "The result of the multiplication is: " << endl;
for (size_t nlndex = 0; nlndex < vecResult.size (); ++ nlndex)
cout << vecResult [nlndex] << ' ';
54
return 0;
Результат
The contents of the first vector are:
0123456789
The contents of the second vector are:
100 101 102 103 104 105 106 107 108 109
i
The result of the multiplication held in the third vector is:
0 101 204 309 416 525 636 749 864 981
Анализ
С троки 5 -1 3 сод ерж ат класс M u l t i p l y . В данном п ри м ере алгоритм s t d : : tr a n s f o r m () используется для умножения содержимого двух диапазонов и сохра
нения результата в третьем. В данном случае рассматриваемые диапазоны содержатся в объектах v e c M u ltip lic a n d , v e c M u l t i p l i e r и v e c R e s u lt класса s t d : : v e c to r . Дру гими словами, функция s t d : : t r a n s f o r m () в строках 35 -39 используется для умноже ния каждого элемента вектора v e c M u lt ip lic a n d на соответствующий элемент вектора v e c M u lt ip lie r и сохраняет результат умножения в векторе v e c R e s u lt . Само умножение осущ ествляется бинарной функцией C M u ltip le : : o p e r a t o r (), которая вызывается для каждого элемента в исходных и результирующих диапазонах векторов. Возвращаемое зна чение оператора o p e r a t o r () сохраняется в векторе v e c R e s u lt.
Таким образом, этот пример демонстрирует применение бинарных функций для вы полнения арифметических операций с элементами в контейнерах STL.
Типичные приложения объектов функций
|
495
|
Бинарный предикат
Функция, которая получает два аргумента и возвращает значение типа b o o l, является бинарным предикатом. Такие функции находят применение в таких алгоритмах библиоте ки STL, как s t d : : s o r t (). Листинг 21.6 демонстрирует применение бинарного предиката, который сравнивает две строки после перевода их в нижний регистр. Такой предикат при меняется при выполнении независящей от регистра сортировки вектора строк, например.
ЛИСТИНГ 21.6. Бинарный предикат для сортировки строк, независящей от регистра_______
#include
#include
using namespace std;
class CompareStringNoCase
{
public:
7: bool operator () (const strings strl, const strings str2) const
8 : {
string strlLowerCase;
1 0 :
// Зарезервировать пространство
strlLowerCase.resize (strl.size ());
// Преобразовать каждый символ в нижний регистр
transform (strl.begin (), strl.end О,
16: strlLowerCase.begin (), tolower);
17:
string str2LowerCase;
str2LowerCase.resize (str2.size ());
transform (str2.begin (), str2.end (),
21: str2LowerCase.begin (), tolower);
2 2 :
return (strlLowerCase < str2LowerCase);
}
};
Анализ
Бинарный предикат, реализованный в операторе o p e r a t o r (), сначала переводит вве-денные строки в нижний регистр, используя алгоритм s t d : : tr a n s f o r m (), как показано
строках 15 и 20, а затем использует оператор сравнения строк o p e r a to r < для возвраще ния результата сравнения.
Вы можете использовать этот двоичный предикат с алгоритмом s t d : : s o r t () для со ртировки динамического массива, содержащегося в векторе строк, как представлено в ли стинге 21.7.
ЛИСТИНГ 21.7. Использование объекта функции класса CompareStringNoCase
для независящей от регистра сортировки вектора строк_______________________________
// Здесь вставьте код класса CompareStringNoCase из листинга 21.6
#include
496 ЗАНЯТИЕ 21. Понятие объектов функций
#include
template
void DisplayContents (const T& Input)
{
7 for(auto iElement = Input.cbegin() // auto, cbegin и cend: C++11
; iElement != Input.cend ()
; ++ iElement )
cout « *iElement « endl;
}
12
int main ()
{
// Определить вектор строк для имен
vector vecNames;
17
// Вставить в вектор несколько примеров имен
vecNames.push_back ("jim");
vecNames,push_back ("Jack");
vecNames.push_back ("Sam");
vecNames.push_back ("Anna");
23
cout « "The names in vector in order of insertion: " << endl;
DisplayContents(vecNames);
cout << "Names after sorting using default std::less<>: "
endl;
sort(vecNames.begin(), vecNames.end());
DisplayContents(vecNames); ’
30
cout « "Names after sorting using predicate that ignores case:"
endl;
sort(vecNames.begin(), vecNames.end(), CompareStringNoCase());
DisplayContents(vecNames);
34
return 0;
}
Результат
The names in vector in order of insertion:
jim
Jack
Sam
Anna
Names after sorting using default std::less<>:
Anna
Jack
Sam
jim
Names after sorting using predicate that ignores case:
Anna
Jack
jim
Sam
Анализ
Вывод отображает содержимое вектора на трех этапах. На первом содержимое отобра жается в порядке вставки. На втором этапе, после сортировки в строке 28 с использова нием заданного по умолчанию предиката сортировки le ss< T > , вывод демонстрирует, что j im располагается не после Ja ck , поскольку эта сортировка зависит от регистра благодаря оператору s t r i n g : : o p e r a t o r s Последняя версия использует класс предиката сортиров ки C o m p a re stг in g N o C a s e o в строке 32 (он реализован в листинге 21.6), гарантирующе го, что j im будет следовать после Ja c k , несмотря на различие в регистре.
Бинарные предикаты применяются во множестве алгоритмов STL. Например, в ал
горитме s t d : : u n i q u e ( ) , удаляющем совпадаю щ ие соседние элементы, в алгоритме
s t d : : s o r t (), осущ ествляю щ ем сортировку, в алгоритме s t d : : s t a b l e s o r t (), осу
ествляющем сортировку в относительном порядке, в алгоритме s t d : : tr a n s f o r m (), позволяющем выполнить операцию с двумя диапазонами, и во многих других алгоритмах библиотеки STL, нуждающихся в бинарном предикате.
Резюме
На этом занятии вы познакомились с функторами (или объектами функций). Вы узна ли, что объекты функций, реализованные в структуре или классе, полезней простых функ ций, поскольку они могут использоваться также для содержания информации состояния. Вы получили понятие о предикатах, которые являются специальным классом объектов функции, и ознакомились с некоторыми практическими примерами, демонстрирующими их удобство.
Do'stlaringiz bilan baham: |