template
|
elementType & element)
|
void FuncDisplayElement
|
(const
|
{
|
<<
|
' ';
|
|
cout << element
|
|
};
|
|
|
|
Функция F u n c D is p la y E le m e n t ()
|
получает один параметр шаблонного типа e l e
|
m en tT y p e, отображаемый на консоли с использованием оператора s t d : :c o u t . Та же функция может иметь и другое представление, в котором реализация функции фактически содержится оператором o p e r a t o r () класса или структуры:
Типичные приложения объектов функций
|
487
|
Структура, способная вести себя как унарная функция template
struct DisplayElement
{
void operator () (const elementType& element) const
{
cout << element << ' ';
}
};
СОВЕТ
Обратите внимание, что DisplayElement - это структура. Если бы это был класс, то оператор operator () должен был бы иметь модификатор доступа public. Структура сродни классу, но ее члены являются открытыми по умол чанию.
Любая из этих реализаций может применяться с алгоритмом библиотеки STL fo r _ each, чтобы отобразить содержимое коллекции на экране, по одному элементу за раз, как представлено в листинге 21.1.
ЛИСТИНГ 2 1 .1 . Отображение содержимого коллекции на экране с использованием унарной функции_____________________________
#include
#include
#include
#include
4
using namespace std;
7 // структура, ведущая себя как унарная функция
template
struct DisplayElement
{
void operator () (const elementType& element) const
{
cout « element « ' ';
}
};
16
int main ()
{
vector veclntegers;
for (int nCount = 0; nCount < 10; ++ nCount)
veclntegers.push_back (nCount);
list listChars;
for (char nChar = 'a'; nChar < 'k'; ++nChar)
listChars.push_back (nChar);
cout << "Displaying the vector of integers: " << endl;
// Отобразить массив целых чисел
488
|
ЗАНЯТИЕ 21. Понятие объектов функций
|
|
32
|
for_each ( veclntegers.begin ()
|
//
|
Начало
|
диапазона
|
33
|
, veclntegers.end
|
()
|
//
|
Конец
|
диапазона
|
34
|
, DisplayElement
|
|
()
|
); //
|
Объект унарной функции
|
35
|
|
|
|
|
|
cout << endl << endl;
cout << "Displaying the list of characters: " << endl;
// Отобразить список символов
for_each ( listChars.begin () // Начало диапазона
41
|
, listChars.end
|
()
|
//
|
Конец
|
диапазона
|
унарной функции
|
42
|
, DisplayElement
|
|
() );
|
// Объект
|
43
|
|
|
|
|
|
|
return 0;
Результат
Displaying the vector of integers:
0123456789
Displaying the list of characters:
a b c d e f g h i j
Анализ
Строки 8 -15 содержат объект функции D is p la y E le m e n t, реализую щ ей оператор o p e r a t o r (). Этот объект функции используется с алгоритмом s t d : : f o r _ e a c h () би блиотеки STL в строках 32 -34 . Алгоритм f o r _ e a c h ( ) получает три параметра: пер
вый — начальный пункт диапазона, второй — конец диапазона, третий — функция, вызы ваемая для каждого элемента в этом диапазоне. Другими словами, код вызывает оператор D is p la y E le m e n t:: o p e r a to r () для каждого элемента в векторе v e c ln te g e r s . Обратите внимание, что вместо структуры D is p la y E le m e n t вы с тем же успехом можете использо вать привычную функцию F u n c D isp la y E le m e n t (). Строки 40-^42 демонстрируют те же возможности для списка символов.
СОВЕТ
Стандарт C++11 вводит лямбда-выражения, являющиеся безымянными объек тами функций.
Версия лямбда-выражения структуры DisplayElement из листинга 21.1 делает весь код компактней, включая определение структуры и ее применение в трех строках функции main (), если заменить строки 32-34:
// Отобразить массив целых чисел, используя лямбда-выражения for_each ( veclntegers.begin () // Начало диапазона
,
|
veclntegers.end
|
()
|
// Конец диапазона
|
} );
|
,
|
[] (int& Element)
|
{cout « element « '
|
|
|
|
// Лямбда-выражение
|
Таким образом, лямбда-выражения - это фантастическое преимущество C++
вы непременно должны изучать их на занятии 22, "Лямбда-выражения языка С++1Г. Листинг 22.1 демонстрирует использование лямбда-функции в алго ритме for_each () для отображения содержимого контейнера вместо объекта функции, как в листинге 21.1.
Типичные приложения объектов функций
|
489
|
Реальное преимущество использования объекта функции, реализованного в структуре, становится очевидным, когда вы в состоянии использовать объект структуры для хране ния информации. Это нечто, чего функция F u n c D is p la y E le m e n t () не может сделать в отличие от структуры, поскольку структура способна хранить атрибуты, кроме оператора o p e r a to r (). Вот несколько измененная версия, в которой используются атрибуты:
template
struct DisplayElementKeepCount
{
int Count;
DisplayElementKeepCount () // Конструктор
{
Count = 0;
}
void operator () (const elementType& element)
{
++ Count;
cout << element « ' ’;
приведенном выше фрагменте структура D isp la y E le m e n tK e e p C o u n t немного мо дифицирована по сравнению с предыдущей версией. Оператор o p e r a t o r () больше не является константной функцией-членом, поскольку он осуществляет инкремент (а следо вательно, изменяет) значения переменной-члена C ount, используемой для хранения коли чества ее вызовов и применяемой для отображения данных. Этот подсчет возможен благо даря открытому атрибуту C ount. Преимущество использования таких объектов функции, способных хранить состояние, показано в листинге 21.2.
ЛИСТИНГ 21.2. Использование объекта функции для хранения состояния________________
#include
#include
#include
using namespace std;
template
struct DisplayElementKeepCount
{
int Count;
9:
1 0 : // Конструктор
1 1 : DisplayElementKeepCount() : Count(0) {}
1 2 :
// Отобразить элемент, хранящий количество!
void operator()(const elementType& element)
++ Count;
17:
|
cout « element«
|
• .
|
18:
|
|
|
19:
|
|
|
2 0 :
490 ЗАНЯТИЕ 21. Понятие объектов функций
int main()
22: {
vector veclntegers;
for(int nCount = 0; nCount< 10; ++ nCount)
veclntegers.push_back(nCount) ;
26:
cout << "Displaying the vector of integers: "<< endl;
// Отобразить массив целых чисел
DisplayElementKeepCount Result;
31:
|
Result = for_each( veclntegers.begin()
|
//
|
Начало
|
диапазона
|
32:
|
, veclntegers.end()
|
//
|
Конец
|
диапазона
|
, DisplayElementKeepCount() ); // объект функции
cout << endl<< endl;
// Использование хранилища состояния при возвращении значения!
cout << " '" << Result.Count << "' elements were displayed!"
<< endl;
39:
return 0;
}
Результат
Displaying the vector of integers:
0123456789
Do'stlaringiz bilan baham: |