Байланысты: Бьерн Страуструп. Язык программирования С . М Бином, 2011
8.7 Шаблоны типа и производные классы Мы уже видели, что сочетание производных классов (наследование) и шаблонов типа может быть
мощным средством. Шаблон типа выражает общность между всеми типами, которые используются как
его параметры, а базовый класс выражает общность между всеми представлениями (объектами) и
называется интерфейсом. Здесь возможны некоторые простые недоразумения, которых надо избегать.
Два созданных по одному шаблону типа будут различны и между ними невозможно отношение
наследования кроме единственного случая, когда у этих типов идентичны параметры шаблона.
Например:
template class Vector {
/* ... */ }
Vector v1;
Vector v2;
Vector v3;
Здесь v1 и v3 одного типа, а v2 имеет совершенно другой тип. Из того факта, что short неявно
преобразуется в int, не следует, что есть неявное преобразование Vector в Vector:
v2 = v3;
// несоответствие типов
Но этого и следовало ожидать, поскольку нет встроенного преобразования int[] в short[].
Аналогичный пример:
class circle: public shape { /* ... */ };
Vector v4;
Vector v5;
Vector v6;
Здесь v4 и v6 одного типа, а v5 имеет совершенно другой тип. Из того факта, что существует неявное
преобразование circle в shape и circle* в shape*, не следует, что есть неявные преобразования
Vector в Vector или Vector* в Vector* :
v5 = v6;
// несоответствие типов
Дело в том, что в общем случае структура (представление) класса, созданного по шаблону типа, такова,
что для нее не предполагаются отношения наследования. Так, созданный по шаблону класс может
содержать объект типа, заданного в шаблоне как параметр, а не просто указатель на него. Кроме того,
допущение подобных преобразований приводит к нарушению контроля типов:
void f(Vector* pc)
{
Vector* ps = pc;
// ошибка: несоответствие типов
(*ps)[2] = new square;
// круглую ножку суем в квадратное
// отверстие (память выделена для
// square, а используется для circle
}
На примерах шаблонов Islist, Tlink, Slist, Splist, Islist_iter, Slist_iter и SortableVector мы видели, что
шаблоны типа дают удобное средство для создания целых семейств классов. Без шаблонов создание
таких семейств только с помощью производных классов может быть утомительным занятием, а значит,
ведущим к ошибкам. С другой стороны, если отказаться от производных классов и использовать только
шаблоны, то появляется множество копий функций-членов шаблонных классов, множество копий
описательной части шаблонных классов и во множестве повторяются функции, использующие шаблоны
типа.