Бьерн Страуструп - Язык программирования С++. Вступление, глава 1
Страница 35. Множественные реализации


 

1.4.6  Множественные реализации

    Основные средства, поддерживающие объектно-ориентированное
программирование, а именно: производные классы и виртуальные функции,-
можно использовать и для поддержки абстракции данных, если допустить
несколько реализаций одного типа. Вернемся к примеру со стеком:

              template < class T >
              class stack
              {
                  public:
                  virtual void push ( T ) = 0; // чистая виртуальная функция
                  virtual T pop () = 0;      // чистая виртуальная функция
              };

    Обозначение =0 показывает, что для виртуальной функции не требуется
никакого определения, а класс stack является абстрактным, т.е. он может
использоваться только как базовый класс. Поэтому стеки можно использовать,
но не создавать:

            class cat { /* ... */ };
            stack < cat > s;    // ошибка: стек - абстрактный класс

            void some_function ( stack <cat> & s, cat kitty ) // нормально
            {
              s.push ( kitty );
              cat c2 = s.pop ();
              // ...
            }

    Поскольку интерфейс стека ничего не сообщает о его представлении, от
пользователей стека полностью скрыты детали его реализации.

    Можно предложить несколько различных реализаций стека. Например, стек
может быть массивом:

           template < class T >
           class astack : public stack < T >
           {
           // истинное представление объекта типа стек
           // в данном случае - это массив
           // ...
           public:
             astack ( int size );
             ~astack ();

             void push ( T );
             T pop ();
           };

    Можно реализовать стек как связанный список:

              template < class T >
              class lstack : public stack < T >
              {
              // ...
              };

    Теперь можно создавать и использовать стеки:

           void g ()
           {
             lstack < cat > s1 ( 100 );
             astack < cat > s2 ( 100 );

             cat Ginger;
             cat Snowball;

             some_function ( s1, Ginger );
             some_function ( s2, Snowball );
           }

    О том, как представлять стеки разных видов, должен беспокоиться только
тот, кто их создает (т.е. функция g()), а пользователь стека (т.е. автор
функции some_function()) полностью огражден от деталей их реализации.
Платой за подобную гибкость является то, что все операции над стеками
должны быть виртуальными функциями.

 
« Предыдущая статья   Следующая статья »