Скачиваний:
316
Добавлен:
28.03.2021
Размер:
378.53 Кб
Скачать

54. Совместное использование параметризации и принципов наследования.

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

- шаблон класса может быть порожден от обычного класса;

- шаблонный класс может быть производным от шаблонного класса;

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

Дочерний класс наследует как методы, так и переменные-члены от родителя (с учётом ограничений доступа). Эти методы и переменные становятся членами дочернего класса. Поскольку дочерние классы являются полноценными классами, то они могут иметь и свои собственные члены.

Использование наследования означает, что нам не нужно переопределять информацию из родительских классов в дочерних. Мы автоматически получаем методы и переменные-члены суперкласса через наследование, а затем просто добавляем специфичные методы или переменные-члены, которые хотим. Это не только экономит время и усилия, но также является очень эффективным: если мы когда-либо обновим или изменим базовый класс (например, добавим новые функции или исправим ошибку), то все наши производные классы автоматически унаследуют эти изменения!

55. Организация внешнего доступа к компонентам параметризированных классов. Параметризированные классы и статические элементы.

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

template < class Type>

class Queue {

public:

// встроенный конструктор

Queue() : front( 0 ), back( 0 ) { }

};

При определении функции-члена шаблона вне определения самого шаблона следует применять специальный синтаксис для обозначения того, членом какого именно шаблона является функция. Определению функции-члена должно предшествовать ключевое слово template, за которым следуют параметры шаблона. Так, конструктор Queue можно определить следующим образом:

template < class Type>

class Queue {

public:

Queue();

};

template < class Type>

Queue< Type> ::

Queue( ) { front = back = 0; }

За первым вхождением Queue (перед оператором ::) следует список параметров, показывающий, какому шаблону принадлежит данная функция-член. Второе вхождение Queue в определение конструктора (после оператора ::) содержит имя функции-члена, за которым может следовать список параметров шаблона, хотя это и необязательно. После имени функции идет ее определение;. в нем могут быть ссылки на параметр шаблона Type всюду, где в определении обычной функции использовалось бы имя типа.

Функция-член шаблона класса сама является шаблоном. Стандарт C++ требует, чтобы она конкретизировалась только при вызове либо при взятии ее адреса. При конкретизации функции-члена используется тип того объекта, для которого функция вызвана.

В шаблоне класса могут быть объявлены статические данные-члены. Каждый конкретизированный экземпляр имеет собственный набор таких членов.

Определение шаблона статического члена должно быть вынесено за пределы определения самого шаблона класса, которое начинается с ключевого слово template с последующим списком параметров <class T>. Имени статического члена предшествует префикс QueueItem<T>::, показывающий, что этот член принадлежит именно шаблону QueueItem.

Статический член конкретизируется по шаблону только в том случае, когда реально используется в программе. Сам такой член тоже является шаблоном. Определение шаблона для него не приводит к выделению памяти: она выделяется только для конкретизированного экземпляра статического члена. Каждая подобная конкретизация соответствует конкретизации шаблона класса. Таким образом, обращение к экземпляру статического члена всегда производится через некоторый конкретизированный экземпляр класса:

int ival0 = QueueItem::QueueItem_chunk; // ошибка: QueueItem - это не реальный конкретизированный экземпляр

int ival1 = QueueItem<string>::QueueItem_chunk; // правильно

int ival2 = QueueItem<int>::QueueItem_chunk; // правильно