Параметризированные классы (шаблоны)
template <class T1, class T2>
class A
{
T1 i;
T2 j;
public:
A(T1 a, T2 b) {i=a;j=b;}
void show() {cout<<i<<' '<<j<<endl;}
};
int main()
{
A <int,double> ob1(10,0.23);
A <char,char*> ob2('q',"qwert");
ob1.show();
ob2.show();
return 0;
}
Шаблоны функций.
Функция, вычисляющей сумму нескольких аргументов.
#include <iostream>
using namespace std;
#include <string.h>
template <class T1,class T2>
T1 sm(T1 a,T2 b) // описание шаблона
{ return (T1)(a+b); // функции c двумя параметрами
}
template <class T1,class T2,class T3>
T1 sm(T1 a,T2 b,T3 c) // описание шаблона функции
{ return (T1)(a+b+c); // функции c тремя параметрами
}
int main()
{cout<<"вызов функции sm(int,int) = "<<sm(4,6)<<endl;
cout<<"вызов функции sm(int,int,int) = "<<sm(4,6,1)<<endl;
cout<<"вызов функции sm(int,double) = "<<sm(5,3)<<endl;
cout<<"вызов функции sm(double,int,short)= " <<
sm(.4,6,(short)1)<<endl;
// cout<<sm("я изучаю","язык С++")<<endl; error cannot add two pointers
return 0;
}
Передача в шаблон класса дополнительных параметров.
При создании экземпляра класса из шаблона в него могут быть переданы не только типы, но и переменные и константные выражения:
#include <iostream>
using namespace std;
template <class T1,int i=0,class T2>
class cls
{ T1 a;
T2 b;
public:
cls(T1 A,T2 B) : a(A),b(B){}
~cls(){}
T1 sm() //описание шаблона функции суммирования компонент
{ // i+=3; // error member function 'int __thiscall cls<int,2>::sm(void)'
return (T1)(a+b+i); //a=b+i; return a;
}
};
int main()
{ cls <int,1,int> obj1(3,2); // в шаблоне const i инициализируется 1
cls <int,0,int> obj2(3,2,1); // error 'cls<int,0>::cls<int,0>':no overloaded
// function takes 3 parameter s
cls <int,int,int> obj13(3,2,1); // error 'cls' : invalid template argument for 'i',
// constant expression expected
cls <int,int> obj2(3,1); // error (аналогично предыдущей)
cout<<obj1.sm()<<endl;
return 0;
}
Результатом работы программы будет выведенное на экран число 6.
В этой программе инструкция template <class T1,int i=0,class T2> гово-
рит о том, что шаблон класса cls имеет три параметра, два из которых − имена
типов (Т1 и Т2), а третий (int i=0) − целочисленная константа. Значение кон-
станты i может быть изменено при описании объекта cls <int,1,int> obj1(3,2). В
этом случае инициализация константы i в инструкции template не требуется
template <class T1,int i,class T2>
Совместное использование шаблонов и наследования.
Шаблонные классы, как и обычные, могут использоваться повторно.
Шаблоны и наследование представляют собой механизмы повторного использования кода и могут включать полиморфизм. Шаблоны и наследования связаны между собой следующим образом:
- шаблон класса может быть порожден от обычного класса;
- шаблонный класс может быть производным от шаблонного класса;
- обычный класс может быть производным от шаблона класса.
Ниже приведен пример простой программы, демонстрирующей наследование шаблонного класса oper от шаблонного класса vect.
#include <iostream>
using namespace std;
template <class T>
class vect // класс-вектор
{protected:
T *ms; // массив-вектор
int size; // размерность массива-вектора
public:
vect(int n) : size(n) // конструктор
{ ms=new T[size];}
~vect(){delete [] ms;} // деструктор
T &operator[](const int ind) // доопределение операции []
{ if((ind>0) && (ind<size)) return ms[ind];
else return ms[0];
}
};
template <class T>
class oper : public vect<T> // класс операций над вектором
{ public:
oper(int n): vect<T>(n) {} // конструктор
~oper(){} // деструктор
void print() // функция вывода содержимого вектора
{ for(int i=0;i<size;i++)
cout<<ms[i]<<' ';
cout<<endl;
}
};
int main()
{ oper <int> v_i(4); // int-вектор
oper <double> v_d(4); // double-вектор
v_i[0]=5; v_i[1]=3; v_i[2]=2; v_i[3]=4; // инициализация int
v_d[0]=1.3; v_d[1]=5.1; v_d[2]=.5; v_d[3]=3.5; // инициализация double
cout<<"int вектор = ";
v_i.print();
cout<<"double вектор = ";
v_d.print();
return 0;
}
Как следует из примера, реализация производного класса от класса-шаблона в основном ничем не отличается от обычного наследования.
Шаблоны класса и friend.
Для шаблонов класса, как и для обычных классов, могут быть установлены отношения дружественности. Дружественность может быть установлена между шаблонным классом и глобальной функцией, функцией-членом другого (возможно шаблонного класса) или целым классом (возможно шаблонным).
(ПРИМЕР ИЗ КОНСПЕКТА, НО ВЫДАЁТ ОШИБКУ)
template <class T>
class B;
template <class T>
class A
{
T *m;
int size;
public:
A(int size, T *m);
~A();
friend T fun1 (T&);
friend T B<T>::fun2(A<T> &);
};
template <class T>
class B
{
public:
T fun2(A<T> &);
};
template <class T>
void fun1(T &obj)
{
}
int main()
{
int m1[]={1,2,3};
A <int> a1(3,m1);
fun1(a1);
return 0;
}