Язык программирования C++. Вводный курс

Наследование и композиция


Реализация класса PeekbackStack с помощью закрытого наследования от IntArray работает, но необходимо ли это? Помогло ли нам наследование в данном случае? Нет.

Открытое наследование – это мощный механизм для поддержки отношения “ЯВЛЯЕТСЯ”. Однако реализация PeekbackStack по отношению к IntArray – пример отношения “СОДЕРЖИТ”. Класс PeekbackStack содержит класс IntArray как часть своей реализации. Отношение “СОДЕРЖИТ”, как правило, лучше поддерживается с помощью композиции, а не наследования. Для ее реализации надо один класс сделать членом другого. В нашем случае объект IntArray

делается членом PeekbackStack. Вот реализация PeekbackStack на основе композиции:

class PeekbackStack {

private:

           const int static bos = -1;

public:

           explicit PeekbackStack( int size ) :

           stack( size ), _top( bos ) {}

           bool empty() const { return _top == bos; }



           bool full()  const { return _top == size()-1; }

           int  top()   const { return _top; }

           int pop() {

                  if ( empty() )

              /* обработать ошибку */ ;

                  return stack[ _top-- ];

           }

           void push( int value ) {

                  if ( full() )

              /* обработать ошибку */ ;

                  stack[ ++_top ] = value;

           }

           bool peekback( int index, int &value ) const;

private:

            int _top;

      IntArray stack;

};

inline bool

PeekbackStack::

peekback( int index, int &value ) const

{

           if ( empty() )

        /* обработать ошибку */ ;

           if ( index < 0 || index > _top )

     {

                  value = stack[ _top ];

                  return false;

           }

           value = stack[ index ];

           return true;

}

Решая, следует ли использовать при проектировании класса с отношением “СОДЕРЖИТ” композицию или закрытое наследование, можно руководствоваться такими соображениями:

·         если мы хотим заместить какие-либо виртуальные функции базового класса, то должны закрыто наследовать ему;

·         если мы хотим разрешить нашему классу ссылаться на класс из иерархии типов, то должны использовать композицию по ссылке (мы подробно расскажем о ней в разделе 18.3.4);

·         если, как в случае с классом PeekbackStack, мы хотим воспользоваться готовой реализацией, то композиция по значению предпочтительнее наследования. Если требуется отложенное выделение памяти для объекта, то следует выбрать композицию по ссылке (с помощью указателя).



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