Шаблоны классов, назначение и поведение. Двумя важнейшими характеристиками языка С++ верхнего уровня являются : шаблоны (templates) и обработка исключительных ситуаций (exception handling). Эти характеристики поддерживаются всеми современными компиляторами и позволяют достичь двух наиболее заманчивых целей программирования: создания многократно используемых и отказоустойчивых программ. С помощью шаблонов можно создавать родовые функции (generic functions) и родовые классы (generic classes). В родовой функции или классе тип данных, с которым функция или класс работают, задается в качестве параметра. Это позволяет одну и ту же функцию или класс использовать с несколькими различными типами данных без необходимости программировать новую версию функции или класса для каждого конкретного типа данных. Таким образом шаблоны дают возможность создавать многократно используемые программы. Многие алгоритмы логически одинаковы, независимо от типов данных, например алгоритмы сортировки. Благодаря созданию родовой функции можно независимо от типа данных определить суть алгоритма. Родовая функция создается с помощью ключевого слова template. Типовая форма определения функции-шаблона: template <classT> возвращаемое_значение имя_функции (список_параметров) {тело функции} Здесь Т – фиктивное имя типа данных, которое компилятор автоматически заменит именем реального типа данных при создании конкретной версии функции. Слово class означает любой, в том числе абстрактный тип данных. В случае близких по смыслу функций нахождения минимума из двух величин, для разных типов данных, можно определить единственную шаблонную функцию с именем MyMin: template<class T> T MyMin (T x, T y) {if (x<=y) return x; else return y;} которая потенциально поможет работать с неизвестным типом Т. Следующие заготовки шаблонов функций являются синтаксически правильными: template<class T> T Fun1 (T x, T y, intz) template<class T> doubleFun2 (T x, T y) template<class T, class W> W Fun3 (T x, W y, bool z) · Идентификаторы формальных параметров шаблона (T, W) должны хотя бы один раз появляться в списке формальных параметров функции. · Внутри тела шаблонной функции формальные параметры шаблоны могут использоваться наравне с другими реальными типами данных в операторах определения локальных переменных, в операциях приведения типа и так далее, то есть вести себя как полноправные имена типов данных. · Для шаблонных функций, как и для обычных функций, можно писать прототипы, или можно приписывать спецификаторы inline, static(эти спецификаторы должны находиться после списка формальных параметров шаблона и до типа возвращаемого функцией значения). · Инструкция с ключевым словом template должна находиться сразу перед определением шаблонной функции · Текст определений шаблонов функции нужно располагать в тех же самых файлах, в которых осуществляется их вызов, либо в заголовочных файлах (h-файлы). · Нет никакой априорной нужды применять механизм шаблонов функций ради интереса! В первую очередь шаблоны функций имеют полезность в связи с абстрактными типами данных, каковыми являются классы. Механизм шаблонов особо полезен не для глобальных функций, а для шаблонных классов и их методов! Синтаксис описания шаблона класса имеет следующий вид: template<описание_параметров_шаблона> определение_класса В качестве параметров могут применяться как стандартные, так и определенные пользователем типы, шаблоны и типизированные константы. Создадим очень простой родовой класс, реализующий односвязанный список. #include <iostream.h> template<class T> class List { T data; List *next; public: List(T d); //конструктор класса voidadd(List* node) {node -> next=this; next=0;} List* getnext() {returnnext;} T getdata() {return data;} }; template<class T> List <T>:: List(T d) {data=d; next=0;} int main(void) { List <char> start (‘a’); //start - объект List <char> *p, *last; // создание списка last=&start; for (int i=1; i<26; i++) { p=newList<char> (‘a’+i); p -> add (last); last=p; } //вывод списка p=&start; while(p) {cout<<p->getdata(); p=p ->getnext(); } return 0; } Подведем некоторые итоги и перечислим основные правила описания шаблонов: 1. Внутри шаблона класса параметр типа может применяться в любом месте, где допустимо использовать спецификацию типа 2. Область действия параметра шаблона – от точки описания параметра шаблона до конца шаблона класса 3. Методы шаблона класса автоматически становятся шаблонами функций. Если метод описывается вне шаблона класса, то заголовок метода должен иметь следующую структуру: template <описание_параметров_шаблона> возвращаемый-тип имя-класса< параметры-шаблона> :: Описание параметров шаблона в заголовке метода должно соответствовать шаблону класса, с соблюдением количественного и позиционного соответствия. 4. Локальные классы не могут содержать шаблоны в качестве своих элементов. 5. Методы шаблона класса не могут быть виртуальными. 6. Шаблоны классов могут содержать статические элементы, дружественные функции и классы. 7. Внутри шаблона класса нельзя определять шаблоны дружественных функций. 8. Шаблоны классов могут быть производными как от шаблонных, так и от обычных классов, а также являться базовыми как для шаблонов, так и для обычных классов. 15 Конструктор копирования и конструктор перемещения в языке С++ |