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