Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование очередей кольцевой обработки д...docx
Скачиваний:
4
Добавлен:
10.09.2019
Размер:
80.94 Кб
Скачать

Void enqueue(qType); /*добавить элемент в хвост очереди*/ qType dequeue(void); /*извлечь элемент из головы очереди*/

template <class QType> void  /*Спецификация компонентных методов шаблонного класса содержит в своем заголовке ключевое слово template и декларацию параметров класса*/

RingQueue <QType> :: enqueue (QType) {.....} // методы класса

RingQueue <QType> :: dequeue (QType) {.....}

 RingQueue (int);   /*конструктор c целочисленным аргументом класса RingQueue */

RingQueue (int S) : Qsize(s), head(0), tail(0)   {...}; /*Конструктор класса RingQueue должен обнулять указатели очереди, фиксировать размер очереди и динамически выделять память из кучи для буфера очереди, используя операцию new системы программирования С++.

~RingQueue(); /* деструктор для освобождение памяти, распределенной конструктором для буфера очереди, с помощью операции delete*/

В этом случае конструктор и деструктор по умолчанию будут рассматриваться компилятором С++ как подставляемые (inline) функции. В объектном коде компилятор С++ заменит каждую ссылку на inline-функцию непосредственно ее кодом, увеличивая быстродействие программы.

Программирование кругового обслуживания

Для построения алгоритма кругового обслуживания для задачи Иосифа с помощью кольцевой очереди элементов, целесообразно сформировать класс JoeRing, производный от базового класса RingQueue.

Производный класс JoeRing должен наследовать компоненты базового класса RingQueue, содержать собственные частные (private) компоненты-данные и общедоступные (public) компонентные методы, учитывающие специфику обработки круговой очереди в задаче Иосифа, а также определить конкретный тип данных для параметра базового класса, указанный в шаблоне его декларации для абстрактной типизации элементов очереди. Декларацию производного класса JoeRing можно специфицировать следующим образом:

 class JoeRing : public RingQueue <unsigned>   {   private: /*спецификация компонент-данных класса JoeRing*/ 

int count, int threshold, int leader;  public :/*спецификация прототипов собственных компонентных методов*/ 

void load(), int busy(), unsigned find() и void round(); // декларацию прототипов следующих собственных компонентных методов

 JoeRing (int n, int l, int m) : RingQueue <unsigned> (n+1),       leader (l), thresold (m) {}; // Конструктор класса JoeRing с тремя целочисленными аргументами

~JoeRing();  };

В заголовке приведенной декларации класса JoeRing указано имя базового класса (RingQueue), категория наследования public и конкретизация параметра шаблона базового класса <unsigned>.  Целочисленная (unsigned) конкретизация параметра шаблона базового класса RingQueue соответствует характеру обработки данных в рассматриваемой реализации задачи Иосифа, где элементы обслуживания идентифицируются целочисленными номерами. Поэтому естественно определить тип элементов наследованной очереди как unsigned (беззнаковые целые). Соответствующее расширение наследованных компонент шаблонного базового класса до их полного определения автоматически осуществляется компилятором С++.  Категория наследования public, указанная в заголовке декларации класса JoeRing разрешает обращаться к наследованным защищенным компонентам базового класса в компонентных методах производного класса, а также во внешних функциях программы, вызывая их через объекты производного класса.

В базовом классе рекомендуется применять защищенные (protected) компоненты вместо приватных, чтобы обеспечить доступ к ним в методах производного класса. Для любой категории наследования непосредственный доступ к частным компонентам базового класса в производном классе запрещен и реализуется через соответствующие общедоступные наследованные методы базового класса.

В спецификацию собственных частных компонент производного класса JoeRing рекомендуется включить объявление 3-х целочисленных (int) полей count, threshold и leader. Компоненты count и thresold следует использовать для хранения текущего и предельного значений счетчика шагов по кругу обслуживания, соответственно, компонента leader должна указывать номер ведущего элемента, с которого начинается круговой отсчет в задаче Иосифа.  Компонентный метод void JoeRing ::load() следует применять для загрузки кольцевого буфера наследованной очереди обслуживания в диапазоне от 1 до (qsize-1). Для записи номеров элементов в очередь следует использовать наследованный от базового класса RingQueue компонентный метод enqueue(unsigned). Кроме того, компонентный метод load должен обеспечивать циклический сдвиг всех элементов обслуживания в очереди на число позиций заданное компонентой leader. Сдвиг выполняется с целью расположить в голове очереди элемент, с которого должен начинаться обход круга. Для реализации каждой итерации циклического сдвига рекомендуется применять последовательно наследованные от базового класса RingQueue компонентные методы dequeue и enqueue.  Компонентный метод JoeRing ::find() должен обеспечивать поиск очередного удаляемого элемента и возвращать его номер. Для организации поиска рекомендуется инициализировать счетчик шагов (count=1) и поочередно вызывать наследованные методы базового класса RingQueue dequeue и enqueue, пока показания счетчика шагов меньше порогового значения (count<tresold). В результате выполнения этого цикла элемент кандидат для удаления из круга окажется в голове очереди и может быть исключен наследованным от базового класса RingQueue методом dequeue. Компонентный метод JoeRing ::find() должен реализовать алгоритм кругового обслуживания в задаче Иосифа. Для выполнения подготовительных шагов этого алгоритма следует вызвать компонентный метод load. Чтобы обеспечить круговой обход элементов обслуживания с целью поиска кандидатов для удаления, нужно организовать циклический вызов метода find, который возвращает номер исключаемого элемента. Для его отображения в потоке стандартного вывода (stdout) можно использовать библиотечную функцию printf системы программирования С++. Этот цикл должен продолжаться, пока очередь обслуживания не пуста.

Компонентный метод JoeRing ::busy() рекомендуется предусмотреть для оценки текучего заполнения очереди, т. е. число элементов, находящихся в круге обслуживания. Число элементов очереди определяется соотношением значений ее указателей head и tail, наследованных от базового класса RingQueue. Доступ к ним в производном классе разрешен, т. к. они декларированы в базовом классе с модификатором доступа protected. Полученная оценка заполнения передается через код возврата этого компонентного метода. 

Обращение к компонентному методу round может быть реализовано в основной функции main программы joseph через предварительно определенный объект класса JoeRing, например, следующим образом:

   joe.round(); где joe - объект класса JoeRing, обладающий желаемыми значениями параметров задачи Иосифа (число элементов обслуживания, номер ведущего элемента, пороговое значение счетчика шагов). 

Конструктор класса JoeRing с тремя целочисленными аргументами должен инициализировать собственные приватные компоненты leader и thresold желаемыми значениями и вызывать конструктор базового класса RingQueue <unsigned> для инициализации очереди с наследованным кольцевым буфером достаточного размера и размещения требуемого числа номеров элементов обслуживания. Конструктор базового класса RingQueue имеет один целочисленный аргумент, устанавливающий размер очереди данных. Поэтому конструктор производного класса JoeRing также должен иметь соответствующий целочисленный аргумент для передачи конструктору базового класса. И еще два целочисленных аргумента, которые принимают требуемые значения номера ведущего элемента и порогового значения счетчика шагов для инициализации собственных приватных компонент leader и thresold, соответственно. Поскольку все инициализирующие действия выполняет список инициализаций, тело конструктора класса JoeRing может быть пустым {}. Необходимые 3 аргумента могут быть получены путем преобразования соответствующих параметров командной строки вызова программы Joseph в целочисленный формат с помощью библиотечной функции atoi системы программирования С++. Рассмотренный конструктор следует использовать для создания объекта класса JoeRing в основной функции main программы Joseph.  Деструктор ~JoeRing(). производного класса следует специфицировать, чтобы обеспечить неявный вызов деструктора базового класса RingQueue для освобождения памяти, динамически выделенной под буфер очереди. Какая-либо выходная обработка собственных компонент-данных класса JoeRing не является необходимой, поэтому тело деструктора ~JoeRing() целесообразно оставить пустым {}, а его определение включить в декларацию класса.  Компонентные методы класса JoeRing могут иметь достаточно представительный исходный и, следовательно, объектный код. Поэтому их целесообразно специфицировать вне декларации класса, не превращая в inline-подстановки. Например, определение компонентного метода round вне декларации класса может иметь следующий формат:

 void JoeRing :: round() {/*Исходный код метода*/}

Исключением может быть компонентный метод busy, который достаточно прост, чтобы определить его внутри декларации класса JoeRing.