Лекция 9. Шаблоны.pptx
- Количество слайдов: 22
ШАБЛОНЫ
Шаблоны • Один из наиболее сложных и мощных механизмов С++ • С их помощью создаются обобщенные функции и классы, которые работают с типом данных, который задается как параметр • То есть одна и та же функция или класс применяется к разным типам данных
Обобщенные функции • Существуют универсальные алгоритмы, работа которых не зависит от типа данных • Например, алгоритм сортировки применяется как к массиву целых, так и вещественных чисел • Обобщенная функция позволяет реализовать подобные универсальные операции, а сам тип передается в функцию как параметр
Объявление обобщенной функции template <class Ттип> тип возвращаемого значения Имя_функции (список параметров) { // тело функции } Ттип – задает тип данных, с которым работает функция
Пример обобщенной функции template <class X> void swapsargs(X &a, X &b) { X temp; temp = a; a =b; b=temp; } int main() { int i=10, j=20; double x=10. 9, y=99, 9; char a=‘x’, b=‘m’; cout << “i, j” << i << ‘ ‘ << j << ‘n’; cout << “x, y” << x << ‘ ‘ << y << ‘n’; cout << “a, b” << a << ‘ ‘ << b << ‘n’; swapsargs(i, j); swapsargs(x, y); swapsargs(a, b); cout << “i, j” << i << ‘ ‘ << j << ‘n’; cout << “x, y” << x << ‘ ‘ << y << ‘n’; cout << “a, b” << a << ‘ ‘ << b << ‘n’; return o; }
Шаблон функции вычисления модуля числа #include <iostream> using namespace std; ----------------------------template <class T> //Шаблон функции! T abs(T n) { return (n < 0) ? -n : n; } ----------------------------int main() { int 1 = 5; int 2 = -6; long lon 1 = 70000 L; long lon 2 = -80000 L; double dub 1 = 9. 95; double dub 2 = -10. 15; //осуществления вызовов cout << "nabs(" << int 1 << ")=" << abs(int 1); //abs(int) cout << "nabs(" << int 2 << ")=" << abs(int 2); //abs(int) cout << "nabs(" << lon 1 << ")=" << abs(lon 1); //abs(long) cout << "nabs(" << lon 2 << ")=" << abs(lon 2); //abs(long) cout << "nabs(" << dub 1 << ")=" << abs(dub 1); //abs(double) cout << "nabs(" << dub 2 << ")=" << abs(dub 2); //abs(double) cout << endl; return 0; }
• Обобщенная функция называется шаблонной функцией • Конкретная версия обобщенной функции, создаваемая компилятором называется специализацией или генерируемой функцией
Функция с двумя обобщенными типами template <class X, class Y> void fun 2 args(X a, Y b) { cout << a << ‘ ‘ << b << ‘n’; } void main() { fun 2 args(“завтра”, 21); fun 2 args(21. 2, ‘q’) }
Явная перегрузка обобщенной функции // шаблон функции template <class X> void swapsargs(X &a, X &b) { X temp; temp = a; a =b; b=temp; } swapsargs(int &a, int &b) { int temp; temp = a; a =b; b=temp; } int main() { int i=10, j=20; double x=10. 9, y=99, 9; char a=‘x’, b=‘m’; swapsargs(i, j); swapsargs(x, y); swapsargs(a, b); cout << “i, j” << i << ‘ ‘ << j << ‘n’; cout << “x, y” << x << ‘ ‘ << y << ‘n’; cout << “a, b” << a << ‘ ‘ << b << ‘n’; return o; }
Новый способ определения специализации template <> void swapsargs <int> (int &a, int &b) { int temp; temp = a; a =b; b=temp; }
Перегрузка шаблонной функции template <class X> void fun(X a) { cout << “first fun”<< a << ‘n’; } template <class X, class Y> void fun(X a, X b) { cout <<“second fun”<< a << ‘ ‘ << b << ‘n’; } void main() { fun(1); fun(2, 3); }
Применение обобщенных функций template <class X> void bubble (X *mas, int count) { register int a, b; X t; for(a=1; a<count; a++) for(b=count-1; b>=a; b--) if (mas[b-1]>mas[b]){ t=mas[b-1]; mas[b-1]=mas[b]; mas[b]=t; } }
Задание • Создайте шаблонную функцию, которая уплотняет массив: удаляет несколько элементов из середины массива, а оставшиеся элементы перемещает влево, заполняя образовавшуюся пустоту
Обобщенные классы (ОК) • Если логика класса не зависит от типа данных, то можно создать обобщенный класс • ОК содержит определения алгоритмов, фактический тип данных передается как параметр при создании объекта template <class Ттип> class имя_класса { … } имя_класса <тип> имя_объекта; Функции – члены обобщенного класса автоматически становятся обобщенными
Пример обобщенного класса стек const int SIZE = 5; template <class Stack. Type> class stack { Stack. Type st[SIZE]; int tos; public: stack() {tos = 0; } void push (Stack. Type ob); Stack. Type pop(); }; template <class Stack. Type> void stack <Stack. Type>: : push (Stack. Type ob) { if (tos==SIZE) { cout << “стек полон”; return 0; } st[tos] = ob; tos++; }
template <class Stack. Type> Stack. Type stack <Stack. Type>: : pop () { if (tos==0) { cout << “стек пуст”; return 0; } tos--; return st[tos]; } void main() { stack<char> s 1, s 2; … stack<double> ds 1, ds 2; … stack<char *> ps; … }
struct addr { char name[90]; char city[40]; char zip[12]; } … stack<addr> obj;
Стековый класс в виде шаблона: методы определяются вне класса #include <iostream> using namespace std; const int MAX = 100; template <class Type> class Stack { private: Type st[MAX]; //стек – массив любого типа int top; //индекс вершины стека public: Stack(); //конструктор void push(Type var); //занести число в стек Type pop(); //взять число из стека }; template<class Type> Stack<Type>: : Stack() //конструктор { top = -1; } ----------------------------template<class Type> void Stack<Type>: : push(Type var) //положить число в стек { st[++top] = var; } ----------------------------template<class Type> Type Stack<Type>: : pop() //взять число из стека { return st[top--]; } ----------------------------int main() { Stack<float> s 1; //s 1 – объект класса Stack<float> s 1. push(1111. 1 F); //занести 3 float, вытолкнуть 3 float s 1. push(2222. 2 F); s 1. push(3333. 3 F); cout << "1: " << s 1. pop() << endl; cout << "2: " << s 1. pop() << endl; cout << "3: " << s 1. pop() << endl; Stack<long> s 2; Stack<long> //s 2 – объект класса s 2. push(123123123 L); //занести 3 long, вытолкнуть 3 long s 2. push(234234234 L); s 2. push(345345345 L); cout << "1: " << s 2. pop() << endl; cout << "2: " << s 2. pop() << endl; cout << "3: " << s 2. pop() << endl; return 0; }
Пример шаблона связных списков #include <iostream> using namespace std; template<class TYPE> //структура link<TYPE> struct link //элемент списка ( внутри этой структуры последней ссылки { TYPE data; //элемент данных link* next; //указатель на следующий элемент }; template<class TYPE> //класс linklist<TYPE> class linklist //список ссылок следующую ссылку определение link означает link<TYPE> ) //(внутри этого класса linklist означает linklist<TYPE>) { private: link<TYPE>* first; //указатель на первую ссылку public: linklist() //конструктор без аргументов { first = NULL; } //первой ссылки нет void additem(TYPE d); //добавить данные void display(); //вывести все ссылки }; template<class TYPE> void linklist<TYPE>: : additem(TYPE d) //добавление данных { link<TYPE>* newlink = new link<TYPE>; //создать новую ссылку newlink->data = d; //занести туда данные newlink->next = first; //то есть ссылку на следующий элемент first = newlink; //теперь первая ссылка указывает на данную ссылку } ----------------------------template<class TYPE> void linklist<TYPE>: : display() //вывод всех ссылок { link<TYPE>* current = first; //указатель – на первую ссылку while( current != NULL ) //выйти после { cout << endl << current->data; //вывести на экран current = current->next; //сдвинуться на } } ----------------------------int main() { linklist<double> ld; //ld - объект linklist<double> ld. additem(151. 5); //добавить три числа double в список ld ld. additem(262. 6); ld. additem(373. 7); ld. display(); //вывести весь список ld linklist<char> lch; //lch - объект linklist<char> lch. additem('a'); //три символа (char) – в список lch. additem('b'); lch. additem('c'); lch. display(); //вывести весь список lch cout << endl; return 0; }
Пример ОК с двумя типами template <class Type 1, class Type 2> class exmpl { Type 1 x; Type 2 y; public: exmpl(Type 1 a, Type 2 b) { x=a; y=b; } void show () {cout << x <<y<<‘n’; } }; void main() { exmpl<int, double>ob 1(10, 0. 567); exmpl<char, char *>ob 1(‘X’, “это шаблоны”); ob 1. show (); ob 2. show (); }
Применение шаблонов Создание кода, пригодного к повторному применению в самых разных ситуациях Например, обобщенный класс stack позволяет создавать стеки любых типов Создав и отладив шаблонные функции или класс, не нужно предусматривать отдельные реализации для разных типов данных
Задание Работа в малой группе. Необходимо разработать шаблонный класс для создания и обработки массива. Реализовать обобщенные функции: – добавления элемента в массив – поиска элемента – поиска максимального элемента – поиска минимального элемента – удаление из массива элементов, принадлежащих указанному диапазону
Лекция 9. Шаблоны.pptx