Параметризированные классы (шаблоны)

 

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;

}