
- •Абстрактный базовый класс List
- •Образование класса SeqList из абстрактного базового класса List
- •12.5. Итераторы
- •Абстрактный базовый класс Iterator
- •Образование итераторов для списка
- •Построение итератора SetList
- •Программа 12.4. Использование класса SeqLlstIterator
- •Итератор массива
- •Приложение: слияние сортированных последовательностей
- •Программа 12.5. Слияние сортированных последовательностей
- •Реализация класса Arraylterator
Абстрактный базовый класс List
Абстрактный класс служит шаблоном для своих производных классов. Он может содержать данные и методы, совместно используемые всеми производными классами. С помощью чистых виртуальных функций он обеспечивает, объявления общедоступных методов, которые должны быть реализованы производными классами. В качестве примера мы разрабатываем абстрактный класс List как шаблон для списковых коллекций. Этот класс имеет переменную (член класса) size, используемую для определения методов ListSize и ListEmpty. Эти функции доступны каждому производному классу, обеспечивающему корректное сохранение size при включении или удалении элементов, а также при очистке списка. Несмотря на то, что методы ListSize и ListEmptg представляются в базовом классе, они могут быть либо подменены в производном классе, либо восприняты по умолчанию. Остальные методы объявляются как чистые виртуальные функции базового класса и должны подменяться в производном классе. Функция Insert зависит от конкретного класса коллекций. В одном образовании Insert может помещать данные в последовательный список, а для бинарного дерева или словаря требуется совершенно иной алгоритм включения.
Спецификация класса List
template <class T>
class List
{
protected:
// число элементов списка, обновляемое производным классом
int size;
public:
// конструктор
List(void);
// методы доступа к списку
virtual int Listsize(void) const;
virtual int ListEmpty(void) const;
virtual int Find (T& item) = 0;
// методы модификации списка
virtual void Insert (const T& item) = 0;
virtual void Delete (const T& item) = 0;
virtual void ClearList (void) = 0;
};
Реализация методов класса List
В любом производном классе методы модификации списка должны поддерживать size — член базового класса. Начальное значение 0 присваивается этой переменной конструктором класса List.
// конструктор устанавливает Size в 0
template <class T>
int List<T>::List(void): size(0)
{}
Методы ListSize и ListEmpty класса List зависят только от значения size.
Они реализуются в базовом классе и затем используются любым производным
классом.
// возвратить размер списка
template <class T>
ist List<T>::List(void) const
{
return size;
}
// проверить, пуст ли список
template <class T>
ist List<T>::ListEmpty(void) const
}
return size = =0;
}
Образование класса SeqList из абстрактного базового класса List
Первый раз мы представили класс SeqList в гл. 1, и в последующих главах
показали реализацию массива и связанного списка. Теперь мы снова рассмотрим SeqList в качестве класса, образованного от абстрактного класса List. Методы DeleteFront и GetData отсутствуют в абстрактном классе, так как они применимы только к последовательному списку.
Спецификация класса SeqList
объявление
template <с1ass T>
class SeqList: public List
{
protected:
// связанный список, доступный производным классам
LinkedList<T> llist;
public:
// конструктор
SeqList(void);
// методы доступа к списку
virtual int Find (T& item);
Т GetData(int pos);
// методы модификации списка
virtual void Insert (const Т& item);
virtual void Delete (const Т& item);
Т DeleteFront(void);
virtual void ClearList (void);
// для объекта типа SeqListIterator требуется доступ к llist
friend class SeqListIterator<T>;
}
описание
Являясь наследником абстрактного класса List, класс SeqList должен поддерживать указанные в List операции. Поскольку SeqList реализует последовательный список, в этот производный класс должны быть добавлены метод, GetData, принимающий позицию элемента в качестве параметра, и метод DeleteFront, удаляющий первый элемент списка.
Методы Insert, Delete и ClearList поддерживают защищенный элемент данных базового класса size, поэтому методы ListSize и ListEmpty подменять не нужно.
Прохождение объекта типа SeqList можно выполнить с помощью средства,
называемого итератором (iterator). Этот инструмент, объявляемый как объект
типа SeqListIterator, должен иметь доступ к llist, что обеспечивается объявлением класса SeqListIterator дружественным. Итераторы обсуждаются в следующем разделе. Производная версия класса SeqList включена в файл seqlist2.h.
Реализация производной версии класса SeqList
Основная часть работы по реализации этого класса была сделана в гл. 9. Нам необходимо определить функции Insert, Delete, ClearList и Find. повторяем их определения, сделанные в классе LinkedList, но добавляем поддержку значения size из класса List. Например, метод Insert выглядит следующим образом:
// использовать метод InsertRear для включения элемента в хвост списка
template <class T>
void SeqList<T>::Insert(const T& item)
{
llist.InsertRear(item);
size++; // обновить size в классе List
}
Конструктор производного класса SeqList вызывает конструктор класса List, который обнуляет size.
//конструктор умолчания
//инициализация базового класса
template <class Т>
SeqList<T>::SeqL1st(void): List<T>( )
{}