Ключевое слово class сообщает компилятору, что в шаблоне функции в качестве параметра будут использоваться пользовательские типы данных, то есть классы. Но ни в коем случае не путайте параметр шаблона и шаблон класса. Если нам надо создать шаблон класса, с одним параметром типа int или char, шаблон класса будет выглядеть так:
template < class T>
class Name
{
//тело шаблона класса
};
где T — это параметр шаблона класса, который может принимать любой из встроенных типов данных, то, что нам и нужно.
Класс-шаблон может иметь несколько типов-шаблонов. Достаточно объявить все типы-шаблоны в виде списка, разделенного запятыми. Например, в следующем коротком примере создается класс, использующий два типа-шаблона:
/* данный пример использует два шаблона при определении класса */ #include <iostream.h> template <class Type1, class Type2>
class myclass { Type1 i; Type2 j; public: myclass (Type1 a, Type2 b) { i = a; j = b; } void show () { cout << i << ' ' << j << '\n'; } }; int main() { myclass<int, double> ob1(10, 0.23); myclass<char, char *> ob2('Х', "This is a test"); ob1.show(); // вывод int, double ob2.show(); // вывод char, char * return 0; }
Эта программа выдаст следующий результат на экран: 10 0.23 X This is a test
В программе объявляются два типа объектов. Объект ob1 использует типы данных integer и double. Объект ob2 использует типы данных char и char*. В обоих случаях компилятор автоматически генерирует необходимые данные и функции в соответствии с типом данных, передаваемых конструктору в качестве аргументов.
Итак, класс-шаблон может иметь несколько типов-шаблонов. Достаточно объявить все типы-шаблоны в виде списка, разделенного запятыми.
Шаблон класса определяет типонезависимый класс, который в дальнейшем служит для создания объектов требуемых типов. Если компилятор C++ встречает объявление объекта, основанное на шаблоне класса, то для построения класса требуемого типа он будет использовать типы, указанные при объявлении. Позволяя быстро создавать классы, отличающиеся только типом, шаблоны классов сокращают объем программирования, что, в свою очередь, экономит ваше время.
Пойдем дальше. Теперь предположим, что вашей программе необходимо работать с массивом значений с плавающей точкой, кроме того, что она работает с целочисленным массивом. Один из способов обеспечить поддержку массивов различных типов состоит в создании разных классов. С другой стороны, используя шаблоны классов, вы можете избавиться от необходимости дублировать классы. Ниже представлен шаблон класса, который создает общий класс array:
template<class T, class T1> class array
{ public: array(int size); T1 sum (void); T average_value(void); void show_array(void); int add_value(T); private: T *data; int size; int index; };
Этот шаблон определяет символы типов T и T1. В случае массива целочисленных значений Т будет соответствовать int, а T1 - long. Аналогичным образом для массива значений с плавающей точкой значения Т и Т1 равны float. Теперь потратьте время, чтобы убедиться, что вы поняли, как компилятор С++ будет подставлять указанные вами типы вместо символов Т и Т1.
Далее, перед каждой функцией класса вы должны указать такую же запись со словом template. Кроме того, сразу же после имени класса вы должны указать типы класса, например array <T, T1>::average_value.
Следующий оператор иллюстрирует определение функции average_value для этого класса:
template<class Т, class T1> Т array<T, T1>::average_value(void)
{ T1 sum = 0; int i; for (i = 0; i < index; i++) sum += data[i] ; return (sum / index); }
После создания шаблона вы можете создавать класс требуемого типа, указывая имя класса, а за ним в угловых скобках необходимые типы.
Программа GENARRAY.CPP использует шаблон класса array для создания двух классов, один из которых работает со значениями типа int, а второй — со значениями типа float.
#include <iostream.h>
#include <stdlib.h>
template<class T, class T1> class array
{ public: array(int size); T1 sum(void); T average_value(void); void show_array(void); int add_value(T); private: T *data; int size; int index; };
template<class T, class T1> array<T, T1>::array(int size)
{ data = new T[size]; if (data == NULL)
{ cout << "Недостаточно памяти - программа завершается" << endl; exit(l); }
array::size = size; array::index = 0; }
template<class T, class T1> Tl array<T, Tl>::sum(void)
{ T1 sum = 0; for (int i = 0; i < index; i++) sum += data[i]; return(sum); }
template<class T, class T1> T array<T, T1>::average_value(void)
{ Tl sum =0; for (int i = 0; i < index; i++) sum += data[i]; return (sum / index); }
template<class T, class T1> void array<T, T1>::show_array(void)
{ for (int i = 0; i < index; i++) cout << data[i] << ' '; cout << endl; }
template<class T, class T1> int array<T, T1>::add_value(T value)
{ if (index == size) return(-1); // Массив полон else
{ data[index] = value; index++; return(0); // Успешно } }
void main(void)
{ // Массив из 100 элементов array<int, long> numbers(100)7 // Массив из 200 элементов array<float, float> values(200); int i; for (i = 0; i < 50; i++) numbers.add_value(i); numbers.show_array(); cout << "Сумма чисел равна " << numbers.sum () << endl; cout << "Среднее значение равно " << numbers.average_value() << endl; for (i = 0; i < 100; i++) values.add_value(i * 100); values.show_array(); cout << "Сумма чисел равна." << values.sum() << endl; cout << "Среднее значение равно " << values.average_value() << endl; }
Лучшим способом понять шаблоны классов будет напечатать две копии этой программы. В первой копии замените все символы T и Т1 на int и long. A во второй замените Т и Т1 на float.