Параметризация класса vect
Класс vect часто подлежит параметризации.
template <class T >
class vect {
T *p; // базовый указатель
int size; // число элементов
public:
vect(); // создает массив размерности 10
vect(int n); // создает массив размерности n
vect(const vect &v); // инициализация от vect
vect(const T a[],int n); // инициализация от массива
~vect() { delete p; }
T& operator [](int i); // элемент, проверенный на соответствие границ
vect& operator = (const vect& v);
void print();
};
Определение функций-членов в контексте файла включает метку разрешения имя класса <T>.
template <class T>
vect<T>::vect() { size=10; p=new T[size]; }
template <class T>
vect <T>::vect(int n) { size=n; p=new T[size]; }
template <class T>
vect<T>::vect(const T a[], int n) { size=n; p=new T [size]; for(int i=0; i<size; i++) p[i]=a[i]; }
template <class T>
vect<T>::vect(const vect<T>&v) {
size=v.size; p=new T[size]; for(int i=0; i<size; i++) p[i]=v.p[i]; }
template <class T>
T& vect<T>::operator[](int i) { return p[i]; }
template <class T>
vect<T>& vect<T>::operator = (const vect<T> &v) {
int s=(size < v.size) ? size : v.size;
for(int i=0; i<s; i++) p[i]=v.p[i];
return *this;
}
Код пользователя почти также прост, как и для не параметризованных объявлений. Чтобы использовать эти объявления, в угловых скобках добавляется только специфический тип, который создает экземпляр шаблона. Этот тип может быть встроенным типом, таким как int или типом, определяемом пользователем. Эти шаблоны используются в следующем коде.
main()
{
vect<int> v(8);
vect <float> v1(10);
}
Наследование
Параметризованные типы могут повторно использоваться, благодаря наследованию. Это сравнимо с использованием наследования при порождении обычных классов. Как шаблоны, так и наследование представляют собой механизм для повторного использования кода и могут включать полиморфизм. Они - отличительные особенности С++ и поэтому могут комбинироваться в различных формах. Класс-шаблон может быть порожден от обычного класса. Обычный класс может быть порожден от класса-шаблона. Каждая из этих возможностей ведет к различным отношениям.
В некоторых ситуациях использованием шаблона ведет к недопустимым затратам, выражающимся в размере объектного модуля. Каждый реализованный класс-шаблон требует собственного откомпилированного объектного модуля.
template <class T>
class vect_safe: private vect {
public:
vect_safe() {}
void set(T *d) { vect::set
};
Шаблоны - резюме
-
Шаблоны расширяют понятие функции и класса, предоставляя средства их параметризации, то есть объявления функций и классов в терминах ”любого типа”.
Шаблоны функций
-
Это объявление функции, предваряемое спецификацией шаблона. Спецификация шаблона состоит из ключевого слова template, за которым следует список параметров, заключенный в угловые скобки <>.
-
Имеют параметры типа, которые обозначаются ключевым словом class, за которым следует идентификатор. Ключевое слово class в контексте шаблонов означает любой тип, а не только класс. Идентификатор служит для замещения имени типа. Может быть более одного параметра типа.
-
Шаблоны функций автоматически расширяются транслятором до полного описания функции так, как это необходимо.
// Объявление: максимум из двух значений типа T
template <class T> const T &Max(const T&,const T&);
template <class T> const T & // Определение
Max(const T &a,const T &b) { return a>b ? a : b; }
int i,j; float a,b;
int k=Max(i,j); // Вызов Max(int,int)
int c=Max(a,b); // Вызов Max(float,float)
Если функция-шаблон в рассматриваемом примере должна работать с каким-либо классом, то в этом классе операция должна быть перегружена. В противном случае при связывании программы произойдет ошибка.
-
Шаблоны функций могут быть перегружены другими функциями.
template <class T> const T & Max(const T &,const T &);
template <class T> const T & Max(const T *,int);
int Max(int (*)(int),int (*)(int));
-
Для определенных типов шаблоны функций могут быть перекрыты для того, чтобы выполнять (или не выполнять) какие-либо действия, которые функции-шаблоны не выполняют (или выполняют).
const char * &Max(const char * &c, const char * &d) {/*
Выполняет что-либо, специфичное для char * }