Шрифт:
}
Очевидно, что функция
Larger_than
должна удовлетворять двум условиям. • Ее можно вызывать как предикат, например
pred(*first)
. • Она может хранить значение, например
31
или x
, передаваемое при вызове.
class Larger_than {
int v;
public:
Larger_than(int vv) : v(vv) { } // хранит аргумент
bool operator(int x) const { return x>v; } // сравнение
};
Следует отметить, что это определение представляет собой именно то, что мы требовали от предиката. Теперь осталось понять, как это работает. Написав выражение
Larger_than(31)
, мы (очевидно) создаем объект класса Larger_than
, хранящий число 31
в члене v
. Рассмотрим пример.
find_if(v.begin,v.end,Larger_than(31))
Здесь мы передаем объект
Larger_than(31)
алгоритму find_if
как параметр с именем pred
. Для каждого элемента v алгоритм find_if
осуществляет вызов
pred(*first)
Это активизирует оператор вызова функции, т.е. функцию-член operator, для объекта-функции с аргументом
*first
. В результате происходит сравнение значения элемента, т.е. *first
, с числом 31
. Мы видим, что вызов функции можно рассматривать как результат работы оператора
, аналогично любому другому оператору. Оператор называют также оператором вызова функции (function call operator) или прикладным оператором (application operator). Итак, оператор в выраженииpred(*first)
эквивалентен оператору Larger_than::operator
, точно так же, как оператор []
в выражении v[i]
эквивалентен оператору vector::operator[]
. 21.4.1. Абстрактная точка зрения на функции-объекты
class F { // абстрактный пример объекта-функции
S s; // состояние
public:
F(const S& ss):s(ss) { /* устанавливает начальное значение */ }
T operator (const S& ss) const
{
// делает что-то с аргументом ss
// возвращает значение типа T (часто T — это void,
// bool или S)
}
const S& state const { return s; } // демонстрирует
// состояние
void reset(const S& ss) { s = ss; } // восстанавливает
// состояние
};
Объект класса
F
хранит данные в своем члене s
. По мере необходимости объект-функция может иметь много данных-членов. Иногда вместо фразы “что-то хранит данные” говорят “нечто пребывает в состоянии”. Когда мы создаем объект класса F
, мы можем инициализировать это состояние. При необходимости мы можем прочитать это состояние. В классе F
для считывания состояния предусмотрена операция state
, а для записи состояния — операция reset
. Однако при разработке объекта-функции мы свободны в выборе способа доступа к его состоянию. Разумеется, мы можем прямо или косвенно вызывать объект-функцию, используя обычную систему обозначений. При вызове объект-функция
F
получает один аргумент, но мы можем определять объекты-функции, получающие столько параметров, сколько потребуется.