ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 7) онлайн

Массивы как члены классов

Массивы могут быть использованы в качестве полей класса. Давайте рассмотрим пример, который моделирует компьютерную структуру данных — стек.

Стек работает как пружинное устройство, удерживающее патроны в магази- не. Когда вы помещаете патрон в магазин, стек немного оседает; когда вы выни- маете патрон, то он поднимается. Последний положенный в магазин патрон всег- да будет вынут первым.

Стек — это один из краеугольных камней архитектуры микропроцессоров, используемой в самых современных компьютерах. Как мы упоминали ранее, функции передают аргументы и хранят возвращаемые адреса в стеке. Этот вид стека частично реализован в оборудовании, и к нему удобнее всего получать доступ через язык ассемблера. Однако стек можно полностью реализовать в про- граммном обеспечении. Здесь стек представляет собой полезное устройство для хранения данных в определенной программной ситуации, например такой, как разбор алгебраического выражения.

В нашем примере, программе STAKARAY, создадим простой класс stack.

// stakaray.cpp

// класс стек

#include <iostream>

using namespace std;

///////////////////////////////////////////////////////////

class Stack

{

  private:

    enum { MAX = 10 }; // немного нестандартный синтаксис

    int st [ MAX ];    // стек в виде массива

    int top;           // вершина стека

  public:

 

Stack ( )  // конструктор

      { top = 0; }

    void push ( int var ) // поместить в стек

      { st [ ++top ] = var; }

    int pop ( ) // взять из стека

      { return st [ top-- ]; }

};

///////////////////////////////////////////////////////////

int main ( )

{

  Stack s1;

 

  s1.push ( 11 );

  s1.push ( 22 );

  cout << "1: " << s1.pop ( ) << endl;

  cout << "2: " << s1.pop ( ) << endl;

  s1.push ( 33 );

  s1.push ( 44 );

  s1.push ( 55 );

  s1.push ( 66 );

  cout << "3: " << s1.pop ( ) << endl;

  cout << "4: " << s1.pop ( ) << endl;

  cout << "5: " << s1.pop ( ) << endl;

  cout << "6: " << s1.pop ( ) << endl;

  return 0;

}

 

Важным членом класса stack является массив st. Переменная top типа int хра- нит в себе индекс последнего элемента, положенного в стек; этот элемент распо- лагается на вершине стека.

Размер массива, используемого для стека, определяется переменной MAX в строке

enum { MAX = 10 };

Это определение переменной MAX необычно. Придерживаясь философии ин- капсуляции, предпочтительнее определять константы, используемые в классе, внутри класса — здесь так определена переменная MAX. Таким образом, исполь- зование глобальных констант-переменных для таких целей нецелесообразно. Стандарт C++ дает возможность объявления константы MAX внутри класса:

static const int MAX = 10;

Это означает, что MAX — константа и применяется для всех объектов класса. К сожалению, некоторые компиляторы не позволяют использовать эту конст- рукцию.

Используя обходной путь, мы можем определить такие константы через пе- речисление (это описано в главе 4). Нам не нужно именовать само перечисле- ние, нам нужен только один его элемент:

enum { MAX = 10 };

Здесь определена переменная MAX как целое со значением 10, определение дано внутри класса. Этот подход работает, но он неудобен. Если ваш компиля-

тор поддерживает подход static const, то вам следует использовать его вместо оп- ределения констант внутри класса.

На рис. 7.6 показан стек. Так как на рисунке значения памяти возрастают по направлению сверху низ, то вершина стека находится в нижней части рисунка. При добавлении в стек нового элемента индекс переменной top увеличивается, и она будет показывать на новую вершину стека. При удалении элемента из сте- ка индекс переменной top уменьшается. (Нам не нужно стирать старое значение из памяти при удалении элемента, оно просто становится несущественным.)

Для помещения элемента в стек — процесс называемый проталкиванием — вы вызываете метод push() с сохраняемым значением в качестве аргумента. Для извлечения элемента из стека вы вызываете метод pop(), который возвращает значение элемента.

Программа main() примера STAKARAY применяет класс stack, создавая объект s1 этого класса. Программа помещает два элемента в стек, затем извлекает их и выводит на дисплей. Затем в стек помещаются еще четыре элемента, далее они извлекаются и выводятся. Вот вывод программы:

1:22

2:11

3:66

4:            55

5:44

6:33

Рис. 7.6. Стек

Как вы можете видеть, элементы извлекаются из стека в обратном порядке; последний элемент, помещенный в стек, будет первым элементом, извлеченным оттуда.

 

Заметим небольшое отличие в использовании префиксной и постфиксной формы записи операторов увеличения и уменьшения. В строке

st [ ++top ] = var;

метода push() сначала переменная top увеличивается и будет показывать уже на следующий элемент массива, расположенный за текущим последним элементом. Затем этому элементу присваивается значение переменной var, и он становится новой вершиной стека. В строке

return st [ top-- ];

сначала возвращается значение вершины стека, а затем уменьшается перемен- ная top, так, что она будет уже указывать на предыдущий элемент.

Класс stack является примером важной возможности ООП; он используется для реализации контейнера или механизма для хранения данных. В главе 15 мы увидим, что стек может быть использован не только для этой цели. Он приме- няется в связных списках, очередях, группах и т. д. Механизм хранения данных выбирается в соответствии с требованиями программы. Использование сущест- вующих классов для хранения данных означает, что программисту не нужно бу- дет тратить время на их дублирование.

 

12