Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву
Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Функции-шаблоны (родовые функции)Содержание книги
Поиск на нашем сайте
Определение. Если функции выполняют одинаковые действия, но над данными разных типов, то можно определить одну функцию-шаблон. Определение имеет формат template < class X [, class Y,…]> имя_функции {определение_функции} Причем вместо типа какого-либо аргумента (или всех) или возвращаемого значения может стоять X, Y,…, где X, Y,… – идентификаторы для обозначения произвольного типа данных. Рассмотрим такую задачу: отсортировать массив целых чисел и строк методом пузырька. Вообще говоря, потребовалось бы создать 2 функции для сортировки каждого массива и 2 для обмена двух значений, т.е. 4 функции. Вместо этого напишем 2 функции-шаблона. Определим дополнительно еще 2 функции шаблона – для нахождения max элемента в массиве данных и вывода на экран двух значений данных разного типа.
enum boolean {FALSE, TRUE}; #include "string.hpp" #include "complex.hpp" template <class T> inline void Swap(T & a, T & b) {T c; c = a, a = b, b = c; }
template <class T> T Max(T * a, int n) {int i;T max = a[0]; for(i = 1; i < n; i++) if (a[i] > max) max = a[i]; return max; }
template <class T> void Bul_bul(T * a, int n) // улучшенный «пузырек» с флагом f
{int i, j, f; for(i = 0, f = 1; i < n – 1 && f; i++) for(j = f = 0; j < n – i – 1; j++) if (a[j] > a[j + 1]) {Swap(a[j], a[j + 1]); f = 1;} }
template <class X, class Y> void out2(X a, Y b) {cout << a << ' ' << b; }
Как же будет работать компилятор? При вызове функций-шаблонов в зависимости от типов фактических аргументов компилятор создает различные версии каждой из этих функций. Говорят – компилятор создает порожденную функцию. Процесс генерации порожденной функции называют созданием экземпляра функции. Таким образом, порожденная функция – это конкретный экземпляр функции-шаблона.
void main() { Complex b[5] = {Complex(4, 2), Complex(-3, 4), 1, -2}; String s[5] = {"Петров", "Сибирякова", "Горцев", "Савин", "Буторина"}; int a[10] = {5, 3, 9, 6, 2, 0, 1152, 7, 4}, i; cout << "\n Мax среди строк " << Max(s, 5); // Генерируется экземпляр String Max(String*, int) cout << "\n Мax среди целых чисел " << Max(a, 9); // Генерируется экземпляр int Max(int *, int) Bul_bul(s, 5); // Генерируется экземпляр void Bul_bul(String *, int); cout << "\nОтсортированные строки "; for(i = 0; i < 5; i++) out2(s[i], ' '); // генерируется экземпляр void out2(String, char); Bul_bul(a, 9); // генерируется экземпляр void Bul_bul(int *, int); cout << "\nОтсортированные целые числа\n"; for(i = 0; i < 9; i++) out2(a[i], ' '); // генерируется экземпляр void out2(int, char); cout << "\nКомплексные числа\n"; for(i = 0; i < 5; i++) out2(b[i], " "); // генерируется экземпляр void out2(Complex, char *) out2(endl, "*********"); // генерируется экземпляр void out2(char, char *) getch(); }
При порождении экземпляров функции-шаблона сортировки Bul_bul(...) компилятор сгенерирует также 2 функции Swap – Swap (String &, String &) и Swap(int &, int &).
Программа будет работать при выполнении следующих условий: 1) в классе String должна быть перегружена операции сравнения на >; 2) в классах String и Complex должна быть перегружена операция потокового вывода <<; 3) в классе String, кроме того, должна быть перегружена операция =. Заметим, что функции-шаблоны напоминают перегруженные, но они по своим возможностям более ограничены. В теле таких функций должен быть одинаковый код (тело функции), а перегруженные функции могут содержать различные действия. Классы-шаблоны Так же, как и функции-шаблоны, могут быть определены и классы-шаблоны. Определение. Класс-шаблон – это класс, в котором одни и те же член-данные могут быть разных типов, а действия над ними – одинаковые. Формат определения класса-шаблона template < class X, class Y,...> class имя_класса { X определение член-данных; Y определение член-данных; ....... }; Здесь X и Y – условное обозначение типов данных. Использование такого класса в функциях следующее: имя_класса <конкретные_типы> имя_объекта[(арг-ты констр-а)]; При компиляции для каждого списка типов данных, указанного в < >, будет создан свой экземпляр класса. Рассмотрим пример класса-шаблона Stack. В стек кладутся целые и комплексные числа, строки.
enum boolean {FALSE, TRUE}; #include "string.hpp" #include "Complex.hpp" template <class T> class Stack { T *a; int max, n; public: Stack(int k = 50) {a = new T [max = k]; n = 0; } ~Stack() {delete [ ]a;} // деструктор Stack(Stack<T> &); // конструктор копирования Stack <T> operator = (Stack <T>); void Push(T b) // положить в стек элемент b {if (Full()) {cout << "Стек переполнен!"; return;} a[n++] = b; } T Pop() // удалить элемент из стека {if (!isEmpty()) return a[--n];} T Top() // взять значение с вершины стека {return a[n - 1];} boolean isEmpty() // стек пуст? {if (n = = 0) return TRUE; return FALSE; } boolean Full(); // стек заполнен? friend ostream & operator << (ostream &, Stack <T> &); // потоковый вывод };
template <class T> Stack< T>:: Stack(Stack<T> & b) {int i; max = b.max; n = b.n; a= new T[max]; for(i = 0; i < n; i++) a[i] = b.a[i]; }
template <class T> boolean Stack<T>:: Full() { if (n = = max) return TRUE; // да, заполнен return FALSE; // нет, не заполнен }
template <class T> ostream & operator << (ostream & r, Stack <T> & b) { int i; if (b.isEmpty()) {r << "\nстек пуст"; return r;} for(i = 0; i < b.n; i++) cout << ' ' << b.a[i]; return r; }
template <class T> Stack<T> Stack<T>:: operator = (Stack<T> b) {if (& b!= this) {delete []a; a = new T[max = b.max]; n = b.n; for(int i = 0; i < n; i++) a[i] = b.a[i]; return *this; } }
void main() {Stack <Complex> c(5); // cоздается экземпляр стека комплексных чисел Stack <String> s(5); // cоздается экземпляр стека строк Stack <int> a(2), c; // стек целых чисел Stack <float> b(3); // стек вещественных чисел String b4("bbbb"); // строка “bbbb” int i; c.Push(Complex(2, 3)); // компл. число 2 + 3 * i => в стек комплексных чисел c.Push(3.5); // комп. число 3.5 + 3.5 * i => в стек комплексных чисел s. Push(«dddddd»); // строка “dddddd” => в стек строк s.Push(b4); // строка “bbbb” => в стек строк a.Push(77); // число 77 => в стек целых чисел a.Push(9); // число 9 => в стек целых чисел a.Push(-10); // Сообщение «Стек переполнен!” cout << "\n Стек комплексных чисел "; cout << c; // работают 2 перегруженные операции потокового вывода << для классов Stack и Complex cout<<"\n Стек строк: "; while (!s.isEmpty()) // пока стек не пуст cout << s.Pop(); // работает перегруженная в классе String операция << //Стек строк опустел c = a; // перегруж. операция = переписывает стек целых чисел a в c cout << "\n Стек целых чисел" << c; cout << ”\n В вершине стека число “ << a.Top(); cout << "\nСтек вещественных чисел b = " << b; }
Замечание. Так как действия над данными в классах-шаблонах одинаковые, а типы данных могут быть произвольные, то такие классы еще называют контейнерными. В настоящее время существует большой набор стандартных классов-шаблонов: стеки, очереди, деревья, строки, упорядоченные массивы и др.
|
||
|
Последнее изменение этой страницы: 2021-12-07; просмотров: 105; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.196 (0.008 с.) |