Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет144/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   140   141   142   143   144   145   146   147   ...   256
7.7 Индексация 
Операторная функция operator[] задает для объектов классов интерпретацию индексации. Второй 
параметр этой функций (индекс) может иметь произвольный тип. Это позволяет, например, определять 
ассоциативные массивы. В качестве примера можно переписать определение из $$2.3.10, где 
ассоциативный массив использовался в небольшой программе, подсчитывающей число вхождений 
слов в файле. Там для этого использовалась функция. Мы определим настоящий тип ассоциативного 
массива: 
class assoc { 
struct pair { 
char* 
name; 
int 
val; 
}; 
pair* 
vec; 
int 
max; 
int 
free; 
assoc(const 
assoc&); 
// 
предотвращает копирование 
assoc& operator=(const assoc&); 
// 
предотвращает копирование 
public: 
assoc(int); 
int& 
operator[](const 
char*); 
void 
print_all(); 
}; 
В объекте assoc хранится вектор из структур pair размером max. В переменной free хранится индекс 
первого свободного элемента вектора. 
Чтобы предотвратить копирование объектов assoc, конструктор копирования и операция присваивания 
описаны как частные. Конструктор выглядит так: 
assoc::assoc(int s) 



Бьерн Страуструп.
Язык программирования С++ 
 
193 
max = (s<16) ? 16 : s; 
free = 0; 
vec = new pair[max]; 

В реализации используется все тот же неэффективный алгоритм поиска, что и в $$2.3.10. Но теперь, 
если вектор переполняется, объект assoc увеличивается: 
#include  
int& assoc::operator[](const char* p) 
/* 
работает с множеством пар (структур pair): 
проводит поиск p, возвращает ссылку на целое значение из найденной пары, 
создает новую пару, если 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; idelete 
vec; 
vec 

nvec; 
max 

2*max; 

pp = &vec[free++]; 
pp->name = new char[strlen(p)+1]; 
strcpy(pp->name,p); 
pp->val = 0; 
// начальное значение = 0 
return 
pp->val; 

Поскольку представление объекта assoc скрыто от пользователя, нужно иметь возможность напечатать 
его каким-то образом. В следующем разделе будет показано как определить настоящий итератор для 
такого объекта. Здесь же мы ограничимся простой функцией печати: 
void assoc::print_all() 

for (int i = 0; icout << vec[i].name << ": " << vec[i].val << '\n'; 

Наконец, можно написать тривиальную программу: 
main() //
подсчет числа вхождений во входной 
// поток каждого слова 

const MAX = 256; // больше длины самого длинного слова 
char 
buf[MAX]; 
assoc 
vec(512); 
while (cin>>buf) vec[buf]++; 
vec.print_all(); 

Опытные программисты могут заметить, что второй комментарий можно легко опровергнуть. Решить 
возникающую здесь проблему предлагается в упражнении $$7.14 [20]. Дальнейшее развитие понятие 
ассоциативного массива получит в $$8.8. 
Функция operator[]() должна быть членом класса. Отсюда следует, что эквивалентность x[y] == y[x] 
может не выполняться, если x объект класса. Обычные отношения эквивалентности, справедливые для 
операций со встроенными типами, могут не выполняться для пользовательских типов ($$7.2.2, см. 
также $$7.9). 


Бьерн Страуструп.
Язык программирования С++ 
 
194 


Достарыңызбен бөлісу:
1   ...   140   141   142   143   144   145   146   147   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет