Факультет Информационных Технологий, I семестр Курс: Объектно-ориентированное программирование Семинарист: Анойкин Д.А., http://ccfit.nsu.ru/~den Задание №3. Наследование и полиморфизм. Простой командный процессор Часть 1. Создание контейнера, используя классы 1. Переделайте один из контейнеров (динамический массив или связанный список) на языке C++, используя классы. Все функции, перечисленные в контракте старого контейнера должны быть реализованы и в новой версии. 2. Класс-контейнер должен позволять хранить любые объекты, отнаследованные от специального класса «StorableElement» (вместо варианта с void*, который использовался в первом задании). У этого абстрактного класса есть только одна абстрактная (виртуальная) функция: void virtual print(); которая позволяет распечатать состояние объекта, хранящегося в контейнере. Такой базовый класс необходим, т.к. контейнер должен хранить не просто void*, а указатель на вполне конкретные объекты (это более безопасно). Однако, мы не знаем какие конкретно объекты будут хранится в контейнере, поэтому задаем базовый класс с минимум необходимых функций и полей. Если объекты какого-то класса надо хранить в контейнере, то этот класс просто наследуется от StorableElement. Класс-контейнер должен уметь создавать специальный объект – Iterator, с помощью которого можно перебрать все элементы контейнера по порядку. Класс итератора для конкретного контейнера должен наследовать абстрактный класс Iterator: class Iterator { public: /* возращает true, если есть еще элементы; false – если достигли конца списка и больше нет элементов*/ virtual bool hasNext() = 0; /* возращает текущий элемент, на который указывает курсор, и перемещает курсор на следующий элемент */ virtual StorableElement* next() = 0; } Класс итератора должен быть внутренним классом и как можно более закрытым от внешнего доступа. Функция iterator() у контейнера создает итератор для данного контейнера, а затем мы используем созданный итератор для перебора элементов. Соответственно, можно организовать перебор всех элементов контейнера: Iterator& i=container.iterator(); // возвращает объект класса MyIterator while (i.hasNext()) { MyStorableElement* el = (MyStorableElement*)i.next(); // что-то делаем с полученным элементом } 3. Написать тестовую программу для проверки работоспособности контейнера. Для этого создать класс TestStorableElement, отнаследованный от StorableElement, и использовать объекты этого класса при тестировании контейнера. Часть 2. Создание простого командного процессора 1. Реализовать программу, выполняющую ограниченный набор команд. Команды и аргументы к ним записываются в файле. Каждая команда имеет свой собственный 1 Факультет Информационных Технологий, I семестр Курс: Объектно-ориентированное программирование Семинарист: Анойкин Д.А., http://ccfit.nsu.ru/~den набор аргументов. Если процессор не знает какую либо команду, то он выводит сообщение об ошибке и продолжает работать со следующей командой. 2. Необходимо реализовать следующие команды: Название Аргументы Описание Примеры Print <строка> Распечатать на экране строку, заданную в print Hello World аргументе createfile <file> Создать файл c именем <file>. Если файл createfile test.txt уже существует, то пересоздать. Запросить ввод данных от пользователя (одна строка), записать введенные данные в файл. exec <command> Запустить командную строку, что записана exec notepad.exe в <command>. Используйте функцию test.txt system() из библиотеки "linesystem.h". copy test.txt test2.txt increment <file> Прочитать содержимое файла <file> и increment test.txt проинтерпретировать его как int. Если в int не конвертируется, то выдать сообщение об ошибке и завершить работу. Иначе увеличить полученное число на 1 и перезаписать в файл. decrement <file> Прочитать содержимое файла <file> и decrement test.txt проинтерпретировать его как int. Если в int не конвертируется, то выдать сообщение об ошибке и завершить работу. Иначе уменьшить полученное число на 1 и перезаписать в файл. viewfile <file> Вывести содержимое файла c именем viewfile test.txt <file> на экран. Если файла не существует, то показать сообщение об ошибке и завершить работу. Пример программы для командного процессора (test.prg): print Hello print Please input your age createfile age.txt increment age.txt increment age.txt print It is your age in the 2005 year viewfile age.txt print Please type mail to authors of this simple stupid program in the Notepad exec notepad.exe age.txt Запуск прграммы: cmdproc.exe test.prg 3. Каждая команда представляется в виде класса, отнаследованного от абстрактного класса (интерфейса) Command. У этого интерфейса есть по крайней мере 2 метода: 2 Факультет Информационных Технологий, I семестр Курс: Объектно-ориентированное программирование Семинарист: Анойкин Д.А., http://ccfit.nsu.ru/~den void virtual init (const char* args); void virtual execute(); Абстрактный класс, реализация отсуствует Command void virtual execute()=0; Наследование PrintCommand void virtual execute() { printf(“%s”, arg); } CreateFileCommand void virtual execute() { FILE f = … } Конкретные классы. Описана реализация абстрактых функций. 4. Управление командами возложено на класс CommandManager. a. Функция main() создает объект класса CommandManager. При инициализации объекта этого класса ему подается имя файла с программой (в конструкторе или с помощью специальной функции). Он читает программу и разбирает команды. b. Для каждой команды он создает объект соответсвующего класса и инициализирует с помощью функции init(). Полученный объект кладется в «список команд» являющийся полем класса CommandManager и доступный только ему. В качестве списка используйте список, реализованный в первой части задания. Обратите внимание, что если выбудете хранить объекты Command в списке, то надо будет дополнительно отнаследовать Command от StorableElement. c. После регистрации всех команд CommandManager обращается к созданному списку и последовательно запускает выполнение всех команд, используя метод execute(). Не надо запускать команды на исполнение в конструкторе CommandManager. Лучше используйте отдельную функцию. 3