7.3.2 Реализация
7.3.2 Реализация
Реализующие slist функции в основном просты. Единственая настоящая сложность – что делать в случае ошибки, если, например, пользователь попытается get() что-нибудь из пустого списка. Мы обсудим это в #7.3.4. Здесь приводятся определения членов slist. Обратите внимание, как хранение указателя на последний элемент кругового списка дает возможность просто реализовать оба действия append() и insert():
int slist::insert(ent a) (* if (last) last-»next = new slink(a,last-»next); else (* last = new slink(a,0); last-»next = last; *) return 0; *)
int slist::append(ent a) (* if (last) last = last-»next = new slink(a,last-»next); else (* last = new slink(a,0); last-»next = last; *) return 0; *)
ent slist::get() (* if (last == 0) slist_handler(«get fromempty list»); // взять из пустого списка slink* f = last-»next; ent r f-»e; if (f == last) last = 0; else last-»next = f-»next; delete f; return f; *)
Обратите внимание, как вызывается slist_handler (его описание можно найти в #7.3.4). Этот указатель на имя функции используется точно так же, как если бы он был именем функции. Это является краткой формой более явной записи вызова:
(*slist_handler)(«get fromempty list»);
И slist::clear(), наконец, удаляет из списка все элементы:
void slist::clear() (* slink* l = last;
if (l == 0) return; do (* slink* ll = l; l = l-»next; delete ll; *) while (l!=last); *)
Класс slist не обеспечивает способа заглянуть в список, но только средства для вставления и удаления элементов. Однко оба класса, и slist, и slink, описывают класс slist_iterator как друга, поэтому мы можем описать подходящий итератор. Вот один, написанный в духе #6.8:
class slist_iterator (* slink* ce; slist* cs; public: slist_iterator(slist amp; s) (* cs = amp;s; ce = cs-»last; *)
ent operator()() (* // для индикации конца итерации возвращает 0 // для всех типов не идеален, хорош для указателей ent ret = ce ? (ce=ce-»next)-»e : 0; if (ce == cs-»last) ce= 0; return ret; *) *);