Байланысты: Бьерн Страуструп. Язык программирования С . М Бином, 2011
7.8 Вызов функции Вызов функции, т.е. конструкцию выражение(список-выражений), можно рассматривать как бинарную
операцию, в которой выражение является левым операндом, а список-выражений - правым. Операцию
вызова можно перегружать как и другие операции. В функции operator()() список фактических
параметров вычисляется и проверяется по типам согласно обычным правилам передачи параметров.
Перегрузка операции вызова имеет смысл прежде всего для типов, с которыми возможна только одна
операция, а также для тех типов, одна из операций над которыми имеет настолько важное значение,
что все остальные в большинстве случаев можно не учитывать.
Мы не дали определения итератора для ассоциативного массива типа assoc. Для этой цели можно
определить специальный класс assoc_iterator, задача которого выдавать элементы из assoc в
некотором порядке. В итераторе необходимо иметь доступ к данным, хранимым в assoc, поэтому он
должен быть описан как friend:
class assoc {
friend class assoc_iterator;
pair*
vec;
int
max;
int
free;
public:
assoc(int);
int&
operator[](const
char*);
};
Итератор можно определить так:
class assoc_iterator {
const assoc* cs;
//
массив assoc
int
i;
// текущий индекс
public:
assoc_iterator(const assoc& s) { cs = &s; i = 0; }
pair*
operator()()
{ return (ifree)? &cs->vec[i++] : 0; }
};
Массив assoc объекта assoc_iterator нужно инициализировать, и при каждом обращении к нему с
помощью операторной функции () будет возвращаться указатель на новую пару (структура pair) из этого
массива. При достижении конца массива возвращается 0:
main()
// подсчет числа вхождений во входной
// поток каждого слова
{
const MAX = 256;
// больше длины самого длинного слова
char
buf[MAX];
assoc
vec(512);
while (cin>>buf) vec[buf]++;
assoc_iterator
next(vec);
pair*
p;
while ( p = next(vec) )
cout << p->name << ": " << p->val << '\n';
}
Итератор подобного вида имеет преимущество перед набором функций, решающим ту же задачу:
итератор может иметь собственные частные данные, в которых можно хранить информацию о ходе
итерации. Обычно важно и то, что можно одновременно запустить сразу несколько итераторов одного
типа.
Конечно, использование объектов для представления итераторов непосредственно никак не связано с
перегрузкой операций. Одни предпочитают использовать тип итератора с такими операциями, как first(),
next() и last(), другим больше нравится перегрузка операции ++ , которая позволяет получить итератор,
используемый как указатель (см. $$8.8). Кроме того, операторная функция operator() активно
используется для выделения подстрок и индексации многомерных массивов.
Бьерн Страуструп.
Язык программирования С++
195
Функция operator() должна быть функцией-членом.