На этом шаге мы научимся создавать контейнер.
Покажем на простом примере, как создаются контейнерные классы. Сначала следует включить один или несколько заголовочных файлов, содержащихся в подкаталоге INCLUDE\CLASSLIB каталога BC45. Например, для того чтобы воспользоваться стековым контейнером, следует включить заголовочный файл STACKS.H:
#include <classlib\stacks.h>
Затем создайте контейнерный объект одного из классов, содержащихся в заголовочном файле, например TStackAsVector. Поищите конструктор класса в вашем справочнике по библиотекам ВС45.
TStackAsVector(unsigned max = DEFAULT_STACK_SIZE);
Прототип конструктора этого класса свидетельствует о том, что можно задать необязательный параметр, определяющий максимальный размер стека, или же воспользоваться значением по умолчанию, определенным в заголовочном файле RESOURCE.H. Необходимо также снабдить шаблон типом данных, который вы собираетесь в нем хранить. Например, создать стековый контейнер для вещественных объектов двойной точности можно следующим образом:
TStackAsVector<double> myStack(100);
Это объявление создаст контейнер с именем myStack из шаблона класса TStackAsVector, способный хранить до ста вещественных значений двойной точности. Большинство контейнеров автоматически увеличивает свой размер для хранения большего числа данных, поэтому значения просто определяют начальный размер контейнера, они не обязательно ограничивают контейнер фиксированным числом объектов.
После создания контейнера вы можете запоминать и читать из него данные с помощью вызовов одной или нескольких функций-членов, которые частично могут наследоваться из классов-предков. В листинге 1 демонстрируются некоторые функции, используемые для контейнера TStackAsVector.
Замечание. Вы можете скомпилировать STACKED.СРР как DOS- или ЕаsyWin-приложение. Однако в обоих случаях программу следует скомпоновать вместе с библиотекой скомпилированных классов BIDSx.LIB (x - модель памяти):
bсc stacked bidss.lib
BIDS расшифровывается как Borland International Data Structure (структура данных Borland International). Для каждой модели памяти существует свой файл, идентифицируемый последней буквой имени файла: S (small - малая), С (compact - компактная), М (medium - средняя), L (large - большая), Н (huge - огромная), F(flat - линейная 32-битовая).
Для компиляции программы как EasyWin-приложения щелкните правой кнопкой мыши или нажмите <Alt+F10> и выберите TargetExpert. Установите Target Type равным EasyWin и задайте Large или Small Target Model (другие модели памяти тоже годятся однако для Windows-приложений лучше всего подходит Large). Убедитесь, что помечена ячейка Class Library в Standard Libraries. Прочие примеры программ в этом разделе компилируются аналогично.
Листинг 1. STACKED.СРР (демонстрация TStackAsVector)
#include <iostream.h> #include <classlib\stacks.h> #define TRUE 1 #define FALSE 0 // Создать глобальный контейнерный обьект TStackAsVector<double> myStack(100); int main() { double d; int done = FALSE; // Запросить значения и поместить их в стек while (!done && !myStack.IsFull()) { cout << "Введите число (0 - выход): "; cin >> d; // Ввести значение пользователя if (d == 0.0) done = TRUE; //Закончить цикл while else myStack.Push(d); // Поместить d в стек } // Отобразить информацию в стеке int n = myStack.GetItemsInContainer(); cout << endl <<Число объектов в стеке: " << n << endl; if (n > 0) cout << "Вершина стека: " << myStack.Top() << endl << endl; // Извлечь значения из стека и отобразить их while (!myStack.IsEmpty()) cout << myStack.Pop() << endl; return 0; }
Запустите программу STACKED на выполнение и введите несколько вещественных значений с плавающей запятой. Если вы введете 0, программа отобразит число элементов, запомненных в стеке, и значение, находящееся в верхушке стека. В программе извлекаются и отображаются значения из стека, что опорожняет его перед завершением демонстрации. Поскольку структура данных стека основана на принципе "последним вошел - первым вышел", значения будут выводиться в обратном порядке.
Результат работы программы:
Введите число (0 - выход): 9.9 Введите число (0 - выход): 3.14156 Введите число (0 - выход): -88.55 Введите число (0 - выход): 4.32 Введите число (0 - выход): 6.9 Введите число (0 - выход): 0 Число объектов в стеке: 5 Вершина стека: 6.9 6.9 4.32 -88.55 3.14156 9.9
Для определения, достигло ли число элементов стека максимума, указанного при инициализации, следует вызывать функцию IsFull(). Чтобы проверить, пуст ли стек, следует обратиться к функции IsEmpty(). Вы можете вызывать функцию IsFull() перед сохранением объекта в стеке следующим образом:
if (!myStack.IsFull())
myStack.Push(d);
Переменная d имеет тип double. Она не обязательно должна быть объектом класса, порожденным из поставляемого базового класса, как это было необходимо в старой, основанной на использовании объектов, библиотеке. Поскольку все контейнеры новой библиотеки - шаблоны, они подстраиваются под любой тип данных, который вы захотите хранить.
Для извлечения значения следует обратиться к функции Рор(), которая удаляет один объект из стека. Функция Pop() возвращает объект, сохраненный в контейнере. Это может быть копия объекта или указатель на динамический объект, в зависимости от типа контейнера. Обычно следует вызывать функцию IsEmpty() для предотвращения попытки извлечь значение из пустого стека:
if (!myStack.IsEmpty())
d = myStack.Pop(d);
Если вам необходимо только узнать значение, находящееся в верхушке стека, следует обратиться к функции Тор(), возвращающей копию последнего сохраненного объекта или указатель на него, при этом сам объект из стека не удаляется. Опять же, имеет смысл вызвать IsEmpty() для предотвращения обращения к пустому стеку, не имеющему "верхнего" объекта:
if (!myStack.IsEmpty())
d = myStack.Top(d);
Для определения числа объектов, хранящихся в стеке, следует обратиться к функции GetItemsInContainer(). Обращение к ней всегда безопасно:
int n = myStack.GetItemsInContainer();
Большинство контейнерных классов имеют функции с одинаковыми именами, такими, как GetItemsInContainer(). Изучив функции в одном контейнере, вы сразу же будете знать функции и в другом. Однако только стек имеет функции типа Push(), Pop() и Тор().
На следующем шаге мы рассмотрим соглашения именования шаблонов.