Напередвизначені функціональні об’єкти розміщені в заголовочному файлі FUNCTIONAL і показані в таблиці 10.10. Там знаходяться об’єкти, які можуть працювати з більшістю операторів С++. В таблиці символом Т позначений довільний клас, користувача або одного з базових типів. Змінні x i y – об’єкти класу Т, що передаються в функцію у вигляді параметрів.
Таблиця 10.9
Напередвизначені функціональні об’єкти
Функціональний об’єкт
| Повернуте значення
|
T=plus(T,T)
| x+y
|
T=minus(T,T)
| x-y
|
T=times(T,T)
| x*y
|
T=divide(T,T)
| x/y
|
T=modulus(T,T)
| x%y
|
T=negative(T)
| -x
|
bool=equal_to(T,T)
| x==y
|
bool=not_equal_to(T,T)
| x!=y
|
bool=greater(T,T)
| x>y
|
bool=less(T,T)
| x<y
|
bool=greater_equal(T,T)
| x>=y
|
bool=less_equal(T,T)
| x<=y
|
bool=logical_and(T,T)
| x&&y
|
bool=logical_or(T,T)
| x||y
|
bool=logical_not(T)
| !x
|
Як бачимо, наявні функціональні об’єкти для виконання арифметичних, логічних операцій та операцій порівняння. Розглянемо приклад, в якому використовується арифметичний функціональний об’єкт. Будемо працювати з класом airtime, що являє собою значення часу в хвилинах і годинах. В програмі 15.33 демонструється функціональний об’єкт plus<>(), за допомогою якого можна працювати зі значенням об’єктів airtime в контейнері.
//використання алгоритму accumulate() і функціонального обєкту plus()
#include<iostream>
#include<numeric>
#include<list>
#include<conio>
using namespace std;
////////////
class airtime
{private:
int hours;
int minutes;
public:
airtime():hours(0),minutes(0)
{ }
airtime(int h,int m):hours(h),minutes(m)
{ }
void display()const //вивід на екран
{cout<<hours<<":"<<minutes;}
void get() //ввід даних користувачем
{
char dummy;
cout<<"\nVvedit chas (format 12:59) ";
cin>>hours>>dummy>>minutes;
}
//перезавантажена операція
airtime operator +(const airtime right) const
{int temph=hours+right.hours;
int tempm=minutes+right.minutes;
if (tempm>=60)
{temph++; tempm-=60;}
return airtime(temph,tempm);
}
//перезавантажений оператор ==
bool operator==(const airtime& at2) const
{return(hours==at2.hours)&&
(minutes==at2.minutes);}
//перезавантажений оператор <
bool operator<(const airtime& at2) const
{return((hours<at2.hours)||
((hours==at2.hours) && (minutes==at2.minutes))); }
//перезавантажений оператор !=
bool operator!=(const airtime& at2) const
{return!(*this==at2);}
//перезавантажений оператор >
bool operator>(const airtime& at2) const
{return!(*this<at2 && *this==at2);}
};
///////////////////
int main()
{ char answer;
airtime temp,sum;
list<airtime> airlist;
do {
temp.get();
airlist.push_back(temp);
cout<<"Continue (y/n)?";
cin>>answer;
} while (answer!='n');
//підсумовувати всі елементи
sum=accumulate(airlist.begin(),airlist.end(),
airtime(0,0),plus<airtime>() );
cout<<"\nSuma=";
sum.display();
cout<<endl;
getch();
return 0;
}
Програма 15.33
Крім функціонального об’єкту, в цій програмі використовується алгоритм accumulate(). Існують дві версії цієї функції. Версія з трьома аргументами завжди підсумовує (за допомогою перезавантаженого +) значення з заданого діапазоеу. Якщо ж у алгоритму чотири аргументи, як і в нашому прикладі, то можна використовувати довільний алгоритм з приведено в таблиці 9.9.
Чотири аргументи accumulate() – це ітератори першого і останнього елементу діапазону, ініціалізоване значення суми (звичайно 0), а також операція, яку слід застосовувати до елементів. В нашій програмі ми використовуємо додавання, хоча могли б використовувати також множення чи іншу операцію.
Алгоритм accumulate() не тільки ясніший і зрозуміліший, аніж ітерація по контейнеру, але й більш ефективний.
Функціональний об’єкт plus<>() потребує перезавантаження оператора +. Причому він повинен бути перезавантажений для класу airtime. Логічні функціональні об’єкти, такі як logical_and<>(), слід використовувати з об’єктами тих класів, де таке булеве перезавантаження має сенс. Наприклад, в якості об’єкту може виступати звичайна змінна логічного типу.