Шаблоны классов: не только для типов



Параметризовать некоторый класс так, чтобы он работал для любого типа данных - это только половина того, что шаблоны обеспечивают для классов. Другой аспект состоит в том, чтобы дать возможность задания числовых параметров. Это позволяет Вам, например, создавать объекты типов "Вектор из 20 целых", "Вектор из 1000 целых" или "Вектор из 10 переменных типа double".

Основная идея проста, хотя используемый синтаксис может показаться сложным. Давайте в качестве при­мера рассмотрим некоторый обобщенный класс Vector. Как и класс Pair, класс Vector содержит функции Min(), Max(), isEqual(). Однако в нем может быть любое количество участников, а не два. В классе Pair число участни­ков фиксировано и задаются они в качестве аргументов конструктора. В шаблоне Vector вместо этого использу­ется второй параметр заголовка шаблона:

1 2 3 4 5 template <class T, int n> class Vector { public:   Vector();   ~Vector() {delete[] coord;} void newCoord (T x); T Max (); T Min(); int isEqual(); private: T *coord; int current; };

Значение n, заданное в заголовке шаблона не используется в описании класса, но применяется в описании его методов. Конструктор Vector, использующий значение n для задания размера массива, выглядит так:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 // конструктор template <class T, int n> Vector <T, n>::Vector(): { coord = new T[n];   current = 0; }   // метод Max template <class T, int n> T Vector <T, n>::Max(): { T result (coord[0]); // *   for (int i=0; i<n; i++)   if (result < coord[i]) // ** result = coord[i]; // *** }

В конструкторе задается список инициализаций, устанавливающих начальные значения для двух элемен­тов класса. Элемент coord инициализируется адресом динамически размещенного массива размером n и состоя­щего из элементов типа Т, а элемент current инициализируется значением 0.

Опять, заметим, что в качестве Т может выступать почти любой тип. Однако и в этом случае успешная реа­лизация возможна лишь при определенных условиях - для объектов, чей тип передается в шаблон в качестве па­раметра, должны быть определены следующие операции

1. конструктор копирования (*),

2. оператор < (**), и > для метода Max(),

3. оператор = (***).

Имеется несколько вариантов использования шаблонов с параметрами-значениями для динамического раз­мещения массивов различных размеров. Например, можно передать размер массива конструктору. Указание размеров объекта во время конструирования или путем обращения к некоторому методу действительно обеспе­чивает задание размера, однако такой способ не позволяет создать отдельный тип для каждого отдельного раз­мера. Подход с использованием шаблона гарантирует, что размер становится частью типа. Так, Vector с пятью элементами типа double является типом, отличным от Vector с четырьмя элементами типа double.

Хотите ли Вы, чтобы различные размеры были различными типами, зависит от ваших нужд. Если сравне­ние двух векторов с четырьмя и пятью координатами не имеет особого смысла, то было бы неплохо сделать их различными типами. Вместе с тем, в случае классов для матриц, Вы, возможно, не захотите иметь особый тип для каждого размера матриц, так как, например, умножение, работает с матрицами различных размеров. Если Вы столкнетесь с подобной проблемой, то Вам потребуются только разумные проверки времени выполнения, а не контроль типов при компиляции.

Хотя числовые параметры шаблонов часто используются для задания размеров различных элементов, как это было показано для класса Vector, этим их применение не ограничивается. Например, с помощью числовых параметров можно задавать диапазоны значений графических координат в графическом классе.

Наследование в шаблонах классов

Шаблоны классов, как и классы, поддерживают механизм наследования. Все основные идеи наследования при этом остаются неизменными, что позволяет построить иерархическую структуру шаблонов, аналогичную иерархии классов.

Рассмотрим очень простой пример, на котором продемонстрируем, каким образом можно создать шаблон класса, производный из нашего шаблона класса Pair. Пусть это будет класс Trio, в котором к паре элементов a и b из Pair, добавим элемент c.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 template <class T>   class Trio: public Pair <T>   { T c; public:   Trio (T t1, T t2, T t3); ...   };   template <class T>   Trio<T>::Trio (T t1, T t2, T t3): Pair <T> (t1, t2), c(t3)   {}   // Заметим, что вызов родительского конструктора   // также сопровождается передачей типа Т в качестве параметра.

 

Пример использования контейнера vector

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <vector> using namespace std; vector<int> v(10);   int N=3, M=4;   ....   for(int i = 0; i < 10; i++)   {   v[i] = (i+1)*(i+1);    }   for(int i = 9; i > 0; i--)   {   v[i] -= v[i-1];   }   v.resize(15);    for(int i = 10; i < 25; i++)   {   v[i] = (i+1)*(i+1);   }    ...   vector< vector<int> > Matrix(N, vector<int>(M)); // создание матрицы с N   строками и M столбцами.   Matrix [2][3] = 10;    // или    vector< vector<int> > Matrix; Matrix.resize(N, vector<int>(M));   Matrix [2][3] = 10;   ...

 

Пример использования контейнера string

 

1 2 3 4 5 6 7 8 9 10 11 12 13 . . .    string s = "hello"; string s1, s2, s3, s4;   s1 = s.substr(0, 3), // "hel"   s2 = s.substr(1, 3), // "ell"   s3 = s.substr(0, s.length()-1), "hell"   s4 = s.substr(1); // "ello"   . . .

 

 


Дата добавления: 2021-01-21; просмотров: 122; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!