В файле list2.H
// Видимый внутри класса list
class iterator {
public:
iterator (listelem* p = 0) :ptr (p) { }
iterator operator ++ ( );
iterator operator -- ( );
iterator operator ++ (int);
iterator operator -- (int);
listelem* operator -> ( ) { return ptr; };
char& operator* ( ) { return ptr -> data; }
operator listelem* ( ) {return ptr; } // преобразование
private:
listelem* ptr; // текущий listelem или 0
};
Где, например, operator ++ ( ) может быть определен как:
list :: iterator iterator :: operator++ ( )
{
assert (ptr != 0);
ptr = ptr -> next;
return *this;
}
Используем вышеизложенное, чтобы написать перегруженный operator<< ( ) для вывода списка.
ostream& operator<< (ostream& out, list& x)
{
list :: iterator p = x.begin ( ); // получает x.h
out << “список = (“ ;
while (p != 0) {
out << *p << “, “; // получает char&
++p; // продвигает итератор с помощью next
}
cout << “ ) \n”;
return out;
}
При доступе к члену данных соответствующего listelem с помощью llist :: iterator :: operator* ( ) выполняется явное разыменование p.
Функции-членов для списка STL очень много; мы покажем код лишь для самых типичных и еще несколько оставим в качестве упражнений (см. упражнения с 13 на стр. 243 по 16 на стр. 243). Основная операция со списком – это операция push_front ( ), которая помещает элемент в список. Здесь надо позаботится о специальном случае с пустым списком.
В файле list2.h
void list :: push_front (char c)
{
listelem* temp = new listelem (c, h, 0);
if (h !=0) { //был непустой список
h -> prev = temp;
h = temp;
}
else // был пустой список
h = t = temp;
}
Конструктор для listelem создает ячейку списка, которая заполняется. Если перед этим список был пуст, то голова и хвост должны быть правильно инициализованы. Обратите внимание, что указатель next устанавливается на h конструкторов listelem.
STL предоставляет множество конструкторов и деструкторов.
В файле list2.h
// конструкторы
list ( ) : h(0), t(0) ( ) // 0 означает пустой список
list (size_t n_elements, char c);
list (const list& x);
list (iterator a, iterator b);
~list ( ) { release ( ) ; }
Конструктор по умолчанию, создающий пустой список, уже обсуждался. Второй конструктор создает список из n элементов, инициализованных членом данных, передающимися как c.
list :: list (size_t n_elements, char c)
{
assert (n_elements >0);
h = t = 0;
for (size_t i = 0; i < n_elements; ++i)
push_front ( c );
}
Этот конструктор создает список с помощью повторяющихся вызовов push_front ( ).
В определении копирующего конструктора мы совместили итерацию списка и создание списка. Мы проходим по исходному списку, получая значения данных, используемых при создании копии.
list :: list (const list& x)
{
list :: iterator r = x. begin ( );
h = t = 0; // необходимо для пустого списка
while (r != 0)
push_front (*r++);
}
Деструктор вызывает функцию сборки мусора release ( ).
void list :: release ( )
{
while (h != 0)
pop_front ();
}
Логика итератора и предложенных определений должна согласовываться с логикой обычных указателей и операций C++.