Лекция_3_Перегрузка_и_шаблоны функций.ppt
- Количество слайдов: 25
Перегрузка функций и операторов. Шаблоны функций.
1. Перегрузка функций
Одним из характерных свойств объектноориентированного языка, в том числе и С++, является полиморфизм – использование одного имени для выполнения различных действий над различными объектами. Применительно к функциям это называется перегрузкой.
Использование нескольких функций с одним и тем же именем, но с различными типами параметров, называется перегрузкой функций. Цель перегрузки (присвоения одинаковых имен) функций состоит в том, чтобы функция выполнялась по-разному в зависимости от типа и количества ее аргументов. Компилятор определяет, какую функцию вызвать, по типу фактических параметров. Этот процесс называется разрешением перегрузки.
// Возвращает наибольшее из двух целых: int max(int, int); // Возвр. подстроку наибольшей длины: char* max(char*, char*); // Наибольшее из первого и длины второго: int max(int, char*); // Наибольшее из второго и длины первого: int max(char*, int); void f(int a, int b, char* c, char* d) { cout<<max(a, b)<<max(c, d)<<max(a, c) <<max(c, b); }
При вызове функции max компилятор выбирает соответствующий типу фактических параметров вариант функции. Если соответствия не найдено, то выполняются продвижения типов: bool, char -> int float -> double Далее выполняются стандартные преобразования типов: int -> double указатели -> void*
Если соответствие неоднозначное, то выдаётся сообщение об ошибке: float f(float i) { cout<<“func. float=”; return i; } float f(double i){ cout<<“func. double=”; return i; } int main() { float x=10. 09; double y=10. 09; cout<<f(x)<<endl; cout<<f(y)<<endl;
cout<<f(10)<<endl; // Неоднозначность – 10 преобразовать во // float или double? return 0; } Требуется явное приведение типа для константы 10: cout << f((double)10)<< endl;
2. Шаблоны функций
Многие алгоритмы не зависят от типа данных, с которыми они работают (например, сортировка). С помощью шаблона функций можно параметризовать такой алгоритм (тип данных передаётся в качестве параметра). Формат функции-шаблона: template <class Type> заголовок { тело функции } Вместо слова Type может быть любое имя.
Например, функция сортировки методом выбора: template <class Type> void sort_vybor(Type *b, int n) { Type buf; for(int i=0; i<n-1; i++) { int imin=i; for(int j=i+1; j<n; j++) if(b[j]< b[imin]) imin=j; buf=b[i]; b[i]=b[imin]; b[imin]=buf; } }
Главная программа: #include <iostream. h> template <class Type> void sort_vibor(Type *b, int n); int main() { const int n=20; int i, b[n]; for(i=0; i<n; i++) cin>>b[i]; //Ввод sort_vibor(b, n); for(i=0; i<n; i++) cout<<b[i]<<‘ ‘; // Вывод cout<<endl; // Перевод строки
double a[5]={0. 2, 17, -0. 8, 21, 4. 3}; sort_vibor(a, 5); for(i=0; i<5; i++) cout<<a[i]<<‘ ‘; return 0; }
При использовании шаблонов функций функция автоматически перегружает саму себя. Таким образом, функции можно перегрузить 2 способами: 1) Обычными функциями; 2) С помощью шаблонов функций.
Перегрузка операций
С++ допускает перегрузку операторов, таких, как + , – , * , += , -> , ( ) и др. Перегрузку операторов используют, чтобы пользовательские типы данных выглядели в выражениях подобно стандартным типам С++. Запрещено перегружать: тип operator @(список аргументов)
Для сложения комплексных чисел можно применить функцию Add: struct Compl { double re; double im; }; Compl Add(const Compl& x, const Compl& y ) { Compl t; t. re = x. re + y. re; t. im = x. im + y. im; return t; }
Передача по ссылке обеспечивает эффективный вызов функции, без копирования параметров, а константное описание защищает параметры от изменений.
Тип Complex является типом данных пользователя и арифметические операторы для него не определены. Поэтому для естественной записи выражений надо перегрузить оператор сложения: Compl operator +(const Compl& x, const Compl& y ) { Compl t; t. re = x. re + y. re; t. im = x. im + y. im; return t; }
Тогда в главной программе можно использовать перегруженный оператор +: Compl A, B; cout << “Введите А: ”; cin >> A. re >> A. im; cout << “Введите В: ”; cin >> B. re >> B. im; cout <<“А + В = ”<< A +B <<endl;
Аналогично арифметическим операторам, в Си++ допускается перегружать операторы ">>" и "<<". Например, вывести комплексное число на экран можно так: void main() { Compl u, v; u. re = 2. 1; u. im = 3. 6; v. re = 6. 5; v. im = 7. 8; cout<<"Числа равны( « << u. re << "+"<< u. im << "i) и "; cout <<"(" <<v. re <<"+"<<v. im<<"i). n"; }
Результат работы программы : Числа равны(2. 1+3. 6 i)и(6. 5+ 7. 8 i). Для упрощения записи операции вывода комплексного числа на экране можно перегрузить оператор вывода в поток:
ostream& operator <<( ostream& s, const Compl& x ) { s << "(" << x. re << " + " << x. im << "i)"; return s; } void main() { Compl u, v; u. re = 2. 1; u. im = 3. 6; v. re = 6. 5; v. im = 7. 8; cout<<"Числа равны "<< u<<" и "<< v<< ". n"; }
В определении оператора фигурирует тип ostream. Это класс "поток вывода", объектом которого является стандартный поток вывода на экран cout. Для потокового ввода/вывода в файл необходимо перегружать операторы применительно к классам ofstream и ifstream.
Ограничения: 1) Можно перегружать : + - * / % ^ & I ~ ! = == != < > && II >> << ( ) [ ] 2) Нельзя : . . * ? : : : sizeof 3) Нельзя перегружать операции для встроенных типов (int, double, char, bool). 4) Нельзя изменять приоритет операций. 5) Нельзя изменять синтаксис операций.
Лекция_3_Перегрузка_и_шаблоны функций.ppt