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