Язык программирования C++ для профессионалов
d51f8a0c

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


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

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()) полностью огражден от деталей их реализации. Платой за подобную гибкость является то, что все операции над стеками должны быть виртуальными функциями.

on_load_lecture()



Содержание раздела