Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Листинг 10.3






 

#include

int assoc:: operator[](char* p)

/*

работа с множеством пар " pair":

поиск p,

возврат ссылки на целую часть его " pair"

делает новую " pair", если p не встречалось

*/

{

register pair* pp;

for (pp = & vec[free-1]; vec < = pp; pp--)

if (strcmp(p, pp-> name)==0) return pp-> val;

if (free == max) { // переполнение: вектор увеличивается

pair* nvec = new pair[max*2];

for (int i = 0; iname = new char [strlen(p)+1]; i++);

strcpy(pp-> name, p);

pp-> val = 0; // начальное значение: 0

return pp-> val;

}

 

Поскольку представление assoc скрыто, нужен способ его печати. Здесь воспользуемся простой функцией печати:

 

vouid assoc:: print_all()

{

for (int i = 0; i> buf) vec[buf]++;

vec.print_all();

}

Вызов Функции. Вызов функции, то есть запись выражение(список_выражений), можно проинтерпретировать как бинарную операцию, и операцию вызова можно перегружать так же, как и другие операции. Список параметров функции operator() вычисляется и проверяется в соответствие с обычными правилами передачи параметров. Перегружающая функция может оказаться полезной главным образом для определения типов с единственной операцией и для типов, у которых одна операция настолько преобладает, что другие в большинстве ситуаций можно не принимать во внимание.

Для типа ассоциативного массива assoc мы не определили итератор. Это можно сделать, определив класс assoc_iterator, работа которого состоит в том, чтобы в определенном порядке поставлять элементы из assoc. Итератору нужен доступ к данным, которые хранятся в assoc, поэтому он сделан другом:

 

class assoc

{

friend class assoc_iterator;

pair* vec;

int max;

int free;

public:

assoc(int);

int& operator[](char*);

};

 

Итератор определяется как

 

class assoc_iterator

{

assoc* cs; // текущий массив assoc

int i; // текущий индекс

public:

assoc_iterator(assoc& s)

{

cs = & s; i = 0;

}

pair* operator()()

{

return (ifree)? & cs-> vec[i++]: 0;

}

};

 

Надо инициализировать assoc_iterator для массива assoc, после чего он будет возвращать указатель на новую 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())

cout < < p-> name < < ": " < < p-> val < < " \n";

}

 

Итераторный тип вроде этого имеет преимущество перед набором функций, которые выполняют ту же работу: у него есть собственные закрытые данные для хранения хода итерации. К тому же обычно существенно, чтобы одновременно могли работать много итераторов этого типа.

Конечно, такое применение объектов для представления итераторов никак особенно с перегрузкой операций не связано. Многие любят использовать итераторы с такими операциями, как first(), next() и last() (первый, следующий и последний).


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.01 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал