The_Programmer
СОЗДАНИЕ ШАБЛОНА КЛАССА
Предположим, к примеру, вы создаете класс массива, в котором есть методы для вычисления суммы и среднего значения хранимых в массиве чисел. Предположим, что вы работаете с массивом типа int, и ваш класс мог бы выглядеть так:
class array
{
public:
array(int size);
long sum(void);
int average_value(void);
void show_array(void);
int add_value(int);
private:
int *data;
int size;
int index;
};
Следующая программа I_ARRAY.CPP использует класс array ддя работы со значениями типа int.
#include <iostream.h>
#include <stdlib.h>
class array
{
public:
array(int size);
long sum(void);
int average_value(void);
void show_array(void);
int add_value(int) ;
private:
int *data;
int size;
int index;
};
array::array(int size)
{
data = new int [size];
if (data == NULL)
{
cerr << "Недостаточно памяти - программа завершается " << endl;
exit(l);
}
array:: size = size;
array::index = 0;
}
long array::sum(void)
{
long sum = 0;
for (int i = 0; i < index; i++) sum += data[i];
return(sum);
}
int array::average_value(void)
{
long sum = 0;
for (int i = 0; i < index; i++) sum += data[i];
return (sum / index);
}
void array::show_array(void)
{
for (int i = 0; i < index; i++) cout << data[i] << " ";
cout << endl;
}
int array::add_value(int value)
{
if (index == size) return(-1); // массив полон
else
{
data[index] = value;
index++;
return(0); // успешно
}
}
void main(void)
{
array numbers (100); // массив из 100 эл-тов
int i;
for (i = 0; i < 50; i++) numbers.add_value(i);
numbers.show_array();
cout << "Сумма чисел равна " << numbers.sum () << endl;
cout << "Среднее значение равно " << numbers.average_value() << endl;
}
Как видите, программа распределяет 100 элементов массива, а затем заносит в массив 50 значений с помощью метода add_value. В классе array переменная index отслеживает количество элементов, хранимых в данный момент в массиве. Если пользователь пытается добавить больше элементов, чем может вместить массив, функция add_value возвращает ошибку. Как видите, функция average_value использует переменную index для определения среднего значения массива. Программа запрашивает память для массива, используя оператор new, который подробно рассматривается в уроке 31.
Шаблоны классов
По мере того как количество создаваемых вами классов растет, вы обнаруживаете, что некоторый класс, созданный для одной программы (или, возможно, для этой), очень похож на требующийся вам сейчас. Во многих случаях классы могут отличаться только типами. Другими словами, один класс работает с целочисленными значениями, в то время как требующийся вам сейчас должен работать со значениями типа. float. Чтобы увеличить вероятность повторного использования существующего кода, C++ позволяет вашим программам определять шаблоны классов. Если сформулировать кратко, то шаблон класса определяет типонезависимый класс, который в дальнейшем служит для создания объектов требуемых типов. Если компилятор 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);
}
После создания шаблона вы можете создавать класс требуемого типа, указывая имя класса, а за ним в угловых скобках необходимые типы, как показано ниже:
Имя шаблона //----> array <int, long> numbers (100); <------//Типы шаблона
array <float, float> values(200);
Программа 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)
{
cerr << "Недостаточно памяти - программа завершается" << 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.
Объявление объектов, основанных на шаблоне класса
Для создания объектов с использованием шаблона класса вы просто должны указать имя шаблона класса, за которым между левой и правой угловыми скобками укажите типы, которыми компилятор заменит символы Т, T1, T2 и т. д. Затем ваша программа должна указать имя объекта (переменной) со значениями параметров, которые вы хотите передать конструктору класса, как показано ниже:
template_class_name<typel, type2> object_name( parameter1, parameter2);
Когда компилятор C++ встречает такое объявление, он создает класс, основанный на указанных типах. Например, следующий оператор использует шаблон класса array для создания массива типа char, в котором хранится 100 элементов:
array<char, int> small_numbers(100) ;
ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ
Из этого урока вы узнали, что шаблоны классов помогут вам избавиться от дублирования кода программы, если вам необходимы объекты похожих классов, которые отличаются только типом. Поскольку шаблоны классов могут быть сложными, они могут вас смутить. Когда вы определяете ваш класс, начните с определения, как будто бы вы создаете класс для конкретного типа. После того как вы полностью опишете класс, определите какие элементы необходимо изменить, чтобы работать с объектами различных типов. Теперь замените типы этих элементов такими символами, как, например, Т, Т1, Т2 и т.д.
- Программы, представленные в данном уроке, использовали оператор C++ new для динамического (во время выполнения программы) распределения памяти для массива. В уроке 31 вы подробно ознакомитесь с оператором new. Прежде чем перейти к уроку 31, убедитесь, что вы изучили следующее:
- Шаблоны классов позволяют избавиться от дублирования кода для таких классов, чьи объекты отличаются только типом их элементов.
- Для создания шаблона класса предварите определение класса ключевым словом template и символами типов, например Т и T1.
- Далее вы должны предварить определение каждой функции класса таким же оператором с ключевым словом template. Кроме того, укажите типы шаблона между левой и правой угловыми скобками, а выражение в угловых скобках поместите между именем класса и оператором разрешения области видимости, например class_name<T,T1>::function_name.
- Для создания класса с использованием шаблона укажите имя класса и замещающие значения для типов между левой и правой угловыми скобками, например class_name<int, long> object.