
лекция12(Шаблоны).ppt
- Количество слайдов: 17
Шаблоны – наиболее сложные механизм С++, с помощью которого можно создавать обобщенные функции и классы, работающие с типом данных, заданным как параметр. Таким образом, одну и ту же функцию или класс можно применять к разным типам данных, не используя отдельные варианты для каждого типа. Обобщенные (родовые) функции Обобщенная функция определяет универсальную совокупность операций, применяемых к различным типам данных. Тип данных, с которым работает функция передается в качестве параметра, что позволяет использовать эту функцию с данными разных типов. Большинство алгоритмов универсальны по отношению к типам данных (например, поиск наибольшего элемента, сортировка, кодирование и т. д. ).
Обобщенная функция определяет структуру алгоритма независимо от типа данных. Обобщенная функция автоматически перегружает сама себя. Она определяется с помощью ключевого слова template (шаблон). Прототип функции: template <class T_тип> тип_возвр_знач имя_функции (список_параметров) {/*тело функции*/} где T_тип задает тип данных, с которыми работает функция. Этот параметр можно использовать и внутри функции. А при создании конкретной версии обобщающей функции, компилятор автоматически вставляет вместо него фактический тип. Традиционно, обобщенный тип задается с помощью ключевого слова class, но можно использовать и ключевое слово typename.
Пример: … template <class T>void swap (T&x, T&y) {T z; z=x; x=y; y=z; } main() { int i=1, j=2; double a=1. 1, b=2. 2; char x=‘x’, y=‘y’; swap (i, j); cout<<i<<j; swap (a, b); cout<<a<<b; swap(x, y); cout<<x<<y; return 0; }
С шаблонами связано несколько понятий функции: 1) Обобщенная -- это есть функция, объявленная с помощью ключевого слова templatе, называется также шаблонной функцией; 2) Конкретная версия обобщенной функции, создаваемая компилятором, называется специализацией (specialazation) или генерируемой функцией. Конкретизация -- процесс генерации конкретной функции. Другими словами, генерируемая функция является конкретным экземпляром обобщенной функции.
Функция с двумя обобщенными типами Используя список, элементы которого разделены запятой, можно определить несколько обобщенных типов данных в операторе template. #. . . template <class T 1, class T 2> void func (T 1 a, T 2 b) {cout<<a<<b; } main() { func(“студент”, 30); func(1, 1. 01); func(‘x’, ”abs”); … }
Явная перегрузка обобщенной функции #include <iostream. h> template <class T> T sum(T a, T b) {return a+b; } class complex {public: int x, y; complex(int a=0, int b=0) {x=a; y=b; } }; complex sum(complex a, complex b) { complex c; c. x=a. x+b. x; c. y=a. y+b. y; return c; } int main() { complex a(1, 1), b(3, 4), c; cout<< sum(1, 2) << endl << sum(3. 13, 1. 1) << endl; c = sum(a, b); cout << c. x << ‘t’ << c. y; return 0; }
Перегрузка шаблонной функции Для перегрузки спецификации обобщенной функции достаточно создать ещё одну версию шаблона, отличающуюся от остальных списком своих параметров. #. . template <class T> void f(T a) {cout << “функция f(a)”; } template <class T, class M> void f(T a, M b) {сout<< “func f(a, b)”; } int main() { f(1); f(4, 3); return 0; } При определении шаблонной Функции можно смешивать стандартные и обобщенные параметры функции. template <class T> void f(T a, int b, double c, T d); Ограничение на обобщенные функции. Обобщенная функция должна выполнять одну и ту же универсальную операцию для всех версий. Различаться могут только типы данных. Обобщенные функции описывают универсальные алгоритмы.
Обобщенные классы (Шаблонные классы) Можно создать класс, в котором определены все алгоритмы, а фактический тип данных задается в качестве параметра при создании объекта. Обобщенные классы полезны, если логика класса не зависит от типа данных. Примеры: массивы, стеки, очереди. Объявление обобщенного класса имеет вид: template <class T> class имя_класса {/* тело */}; Конкретный экземпляр класса создается следующей синтаксической конструкцией: Имя_класса <тип> имя_объекта; Где <тип> задает тип данных, которыми оперирует класс. Функции-члены обобщенного класса автоматически становятся обобщенными, для их объявления не обязательно использовать ключевое слово template.
#include <iostream. h> int main() const int SIZE=10; { stack<char> s; s. add(‘a’); template <class T> class stack s. add(‘ 03’); s. add(‘c’); int i; { T stk[SIZE]; for (i=0; i<4; i++) cout<< s. del() << int tos; ‘t’; public: stack<double> d; stack() {tos=0; } d. add(0. 12); void add (T x); d. add(3. 14); T del(); d. add(11. 11); }; for (i=0; i<4; i++) cout << d. del() << ‘t’; template <class T> void return 0; stack<T>: : add(T x) } {if (tos==SIZE) cout<< “Стек полон”; else stk[tos++]=x; } template <class T> T stack<T>: : del() { if(tos==0) {cout<< “Стек пуст”; return 0; } else {tos--; return stk[tos]; } }
Использование двух обобщенных типов Шаблонный класс может использовать несколько обобщенных типов. Для этого их следует перечислить в списке шаблонных параметров в объявлении template. Пример: #include … template <class T 1, class T 2> class myclass { T 1 x; T 2 y; public: myclass(T 1 a, T 2 b) {x=a; y=b; } void show() {cout << x << ‘t’ << y << endl; } }; int main() { myclass <int, double> ob 1(1, 0. 1); myclass <char, int> ob 2(‘a’, 10); ob 1. show(); ob 2. show(); return 0; }
В спецификации шаблона обобщенного класса так же можно использовать стандартные типы, т. е. в качестве шаблонных параметров можно применять стандартные аргументы. Синтаксис такого объявления не отличается от объявления обычных параметров функции – необходимо указать тип и имя параметра. #include <iostream. h> template <class T, int SIZE> class array { T a[SIZE]; public: array() { cout << “Введите массив: ”; for(int i=0; i<SIZE; i++) cin >> a[i]; } T& operator[] (int i); }; template <class T, int SIZE> T& array<T, SIZE>: : operator[] (int i) {if (i<0 || i>=SIZE) {cout<<”Выход за пределы массива” << endl; exit(1); } else return a[i]; }
int main() { array<int, 10> int_arr; array<double, 5> double_arr; int i; for (i=0; i<10; i++) cout<< int_arr[i] << ‘n’; for(i=0; i<5; i++) cout<<double_arr << ‘n’; return 0; }
Применение аргументов по умолчанию в шаблонных классах ü Шаблонный класс может иметь аргумент обобщенного типа, значение которого задано по умолчанию. Например: template <class T=int> class my {…}; ü Если при конкретизации объекта не будет указан тип, используется тип int (заданный по умолчанию). ü Стандартные аргументы в шаблонных классах так же могут иметь значение по умолчанию. Они используются при конкретизации объекта, если не заданы явные значения аргументов. ü Синтаксически отличия описания стандартных объектов по умолчанию не отличается от объявления типа по умолчанию для обычных объектов.
Явная перегрузка шаблонной функции Несмотря на то, что обобщенная функция перегружает сама себя, ее можно перегрузить явно. Этот процесс называется явной специализацией. Перегружаемая функция замещает обобщенную функцию, связанную с данной, конкретной версией. Можно создавать явную спецификацию обобщённого класса. Для этих целей используется конструкция template < > Явная спецификация расширяет возможности обобщённых классов, так как она позволяет обрабатывать одну или несколько особых ситуаций, предоставляя компилятору автоматически генерировать остальные спецификации.
Пример: … template <class T> class my { T x; public: my (T a) {x=a; } T get () {return x; } }; /*создаётся явная спецификация целочисленного обобщенного класса*/ template <> class my <int> { int x; public: my (int a) { x=a*a; } int get () {return x; } }; main () {my <double> d (9. 1); my <int> i(5); cout <<d. get()<<‘t’<<i. get(); … }
Ключевые слова typename и export. Ключевое слово typename используется в двух ситуациях. 1). Оно может заменять ключевое слово class в объявлении шаблона. … template <typename T> void swap (T & a, T& b) { T temp; temp=a; a=b; b=temp; } … 2). Ключевое слово typename создаёт обобщённый тип. typename информирует компилятору о том, что некоторое имя используется в объявлении шаблонного класса в качестве имени типа, а не объекта. typename x: : name ob ; // typename говорит , что это имя класса;
Ключевое слово export может предшествовать объявлению template. Оно разрешает пользоваться шаблоном из другого файла, повторяя лишь его объявление, а не всё определение. “+”: позволяет создавать код, пригодный к повторному выполнению. С помощью шаблонов можно создавать схемы, пригодные в самых разных ситуациях. Обобщённые классы и функции обеспечивают механизм, упрощающий программирование. Написав и отладив шаблонный класс мы получаем законченный программный компонент, применять который можно в разных ситуациях.
лекция12(Шаблоны).ppt