Скачать презентацию Полиморфизм Прикладное программирование кафедра прикладной и компьютерной оптики Скачать презентацию Полиморфизм Прикладное программирование кафедра прикладной и компьютерной оптики

d19ac7cd70bfb0afd5948d5a35cbfe4c.ppt

  • Количество слайдов: 29

Полиморфизм Прикладное программирование кафедра прикладной и компьютерной оптики Полиморфизм Прикладное программирование кафедра прикладной и компьютерной оптики

2 Полиморфизм – возможность принимать множество форм, иметь разный смысл в зависимости от ситуации 2 Полиморфизм – возможность принимать множество форм, иметь разный смысл в зависимости от ситуации Полиморфизм в языке С++ позволяет программисту: n n создавать функции, имеющие одинаковые имена, но разные наборы аргументов (перегрузка функций) определять действие операторов для новых АТД (перегрузка операторов)

3 Перегрузка функций – использование одного имени для функций, выполняющих действия с аргументами разных 3 Перегрузка функций – использование одного имени для функций, выполняющих действия с аргументами разных типов void print(double d); void print(Lens l); void print(double x, double y); Если бы не было перегрузки функций print_int(int i); print_char(char c); print_Lens(Lens l);

4 Поиск подходящей перегруженной функции Последовательность поиска n n проверка точного соответствия типов попытка 4 Поиск подходящей перегруженной функции Последовательность поиска n n проверка точного соответствия типов попытка “повышения типов” (short -> int, float -> double. . . ) попытка стандартных преобразований (int -> double, double -> int, . . . ) преобразование явно задаваемое программистом Автоматическое преобразование типов n n bool, char повышается до int < long < float < double Явное преобразование типов n n (тип) выражение тип (выражение) Возвращаемые типы не участвуют в определении какую из перегруженных функций вызвать. float sqrt(float); float sqrt(double); double sqrt(double);

5 Преобразование типов при помощи конструктора // преобразование из double в Complex: : Complex(double 5 Преобразование типов при помощи конструктора // преобразование из double в Complex: : Complex(double x) { m_re=x; m_im=0. ; } // пример использования Complex x; x=Complex(3. 14); // оператор explicit запрещает неявный вызов конструктора для преобразования типа class Matrix { public: explicit Matrix(int size); } Matrix: : Matrix(int size) { m_data=new double[size*size]; }

6 Аргументы функции по умолчанию n описание полного конструктора с параметрами по умолчанию Lens(double 6 Аргументы функции по умолчанию n описание полного конструктора с параметрами по умолчанию Lens(double r 1, double r 2, double D=0. , double d=0. , double n=1. ); n реализация полного конструктора с параметрами по умолчанию Lens: : Lens(double r 1, double r 2, double D, double d, double n) : m_r 1(r 1) , m_r 2(r 2) , m_d(d) , m_D(D) , m_n(n) { } n аргументы по умолчанию должны быть указаны в конце списка аргументов и подряд Lens Lens lens(100. , -100. ); // r 1=100 r 2=-100 D=0 d=0 lens(100. , -100. , 50. ); // r 1=100 r 2=-100 D=50 d=0 lens(100. , -100. , 50. , 10. ); // r 1=100 r 2=-100 D=50 d=10 lens(100. , -100. , 50. , 1. 5); // r 1=100 r 2=-100 D=0 d=10 lens(100. , -100. , 1. 5); // r 1=100 r 2=-100 D=1. 5 d=0 n=1 n=1. 5 n=1

7 Перегрузка операторов Для абстрактного типа данных Complex: n n n * – комплексное 7 Перегрузка операторов Для абстрактного типа данных Complex: n n n * – комплексное умножение + – комплексное сложение ~ – комплексное сопряжение Complex x, y, z; z=x*y; z=x. operator*(y); // явный вызов оператора class Complex { … Complex operator*(const Complex& other) const; … }

8 Перегрузка бинарных операторов // оператор умножения Complex: : operator*(const Complex& other) const { 8 Перегрузка бинарных операторов // оператор умножения Complex: : operator*(const Complex& other) const { return Complex(m_re*other. m_re-m_im*other. m_im, m_re*other. m_im-m_im*other. m_re); } // смешанная арифметика Complex: : operator*(const double& other) const { return Complex(m_re*other, m_im*other); } // пример использования Complex x, z; double y; z=x*y;

9 Перегрузка унарных операторов // унарный минус Complex: : operator-() const { return Complex(-m_re, 9 Перегрузка унарных операторов // унарный минус Complex: : operator-() const { return Complex(-m_re, -m_im); } // сопряжение Complex: : operator~() const { return Complex(m_re, -m_im); } // пример использования Complex x, y; y=-x; y=~x;

10 Перегрузка логических операторов // оператор равенства bool Complex: : operator== (const Complex& other) 10 Перегрузка логических операторов // оператор равенства bool Complex: : operator== (const Complex& other) const { return (m_re == other. m_re && m_im == other. m_im); } // пример использования Complex x, y; if(x==y) { … }

11 Перегрузка оператора присваивания Правила перегрузки оператора присваивания n n аргументом должна быть неизменяемая 11 Перегрузка оператора присваивания Правила перегрузки оператора присваивания n n аргументом должна быть неизменяемая ссылка на экземпляр данного класса перед присваиванием необходимо сделать проверку на присваивание самому себе присваивание должно быть поэлементное оператор должен возвращать ссылку на самого себя // оператор присваивания Complex& Complex: : operator=(const Complex& other) { if(this != &other) { m_re=other. m_re; m_im=other. m_im; } return *this; } // пример использования Complex x, y, z; x=y=z=1;

12 Перегрузка операторов с присваиванием Правила перегрузки с присваиванием n n аргументом должна быть 12 Перегрузка операторов с присваиванием Правила перегрузки с присваиванием n n аргументом должна быть неизменяемая ссылка на экземпляр данного класса оператор должен возвращать ссылку на самого себя // умножение с присваиванием Complex& Complex: : operator*=(const Complex& other) { Complex temp(*this); m_re=temp. m_re*other. m_re - temp. m_im*other. m_im; m_im=temp. m_re*other. m_im + temp. m_im*other. m_re; return *this; } // пример использования Complex x, y; x*=y;

13 Перегрузка преобразования типов // преобразование типа Complex в double Complex: : operator double() 13 Перегрузка преобразования типов // преобразование типа Complex в double Complex: : operator double() const { return (m_re*m_re-m_im*m_im); } // пример использования Complex x; double y; y=double(x);

14 Перегрузка индексирования // индексирование double& matrix: : operator() (int i, int j) { 14 Перегрузка индексирования // индексирование double& matrix: : operator() (int i, int j) { return (p[i][j]); // или p[i*size+j]; } // пример использования matrix x; double y; y=matrix(1, 1); // доступ к элементу (1, 1)

15 Перегрузка операторов ввода/вывода Оформляются как дружественные функции класса // описание friend ostream& operator<< 15 Перегрузка операторов ввода/вывода Оформляются как дружественные функции класса // описание friend ostream& operator<< (ostream& out, const Complex& x); friend istream& operator>> (istream& out, Complex& x); // объявление ostream& operator<< (ostream& out, const Complex& x) { return (out<<”(“<

16 Неперегружаемые операторы Оператор : : левый и правый операнд являются не значениями, а 16 Неперегружаемые операторы Оператор : : левый и правый операнд являются не значениями, а именем Оператор. правый операнд является именем Оператор. * правый операнд является именем Оператор ? : арифметический оператор имеет специфическую семантику Оператор new операнд является именем, кроме того выполняет небезопасную процедуру Оператор delete не используется без new, кроме того выполняет небезопасную процедуру Нельзя определить новые операторы См. пример программы

17 Параметрический полиморфизм позволяет многократно использовать один и тот же код применительно к разным 17 Параметрический полиморфизм позволяет многократно использовать один и тот же код применительно к разным типам n тип указывается как параметр функции или класса Шаблоны (templates) – средство для реализаций параметризированных классов и функций на языке С++

18 Шаблоны функций void swap(int& x, int& y) { int temp; temp=x; x=y; y=temp; 18 Шаблоны функций void swap(int& x, int& y) { int temp; temp=x; x=y; y=temp; } template void swap(TYPE& x, TYPE& y) { TYPE temp; temp=x; x=y; y=temp; } // использование шаблона double x=1, y=5; swap (x, y); // TYPE заменяется на double n Инстанцирование – генерация функции по шаблону и ее аргументу См. пример программы

19 Шаблоны функций с несколькими параметрами // пример 1 template<class PAR 1, class PAR 19 Шаблоны функций с несколькими параметрами // пример 1 template bool transform(PAR 1 x, PAR 2& y) { if(sizeof(y) < sizeof(x)) { return false; } y=(PAR 2)x; return true; } // пример 2 template PAR factorial() { PAR sum=1; i=1; while(i<=n) { sum*=i; i++; } return sum; }

20 Пример шаблона класса template <class PAR> class Complex { protected: PAR m_re, m_im; 20 Пример шаблона класса template class Complex { protected: PAR m_re, m_im; //вещественная и мнимая часть public: Complex(); // конструктор по умолчанию Complex(PAR re, PAR im=PAR(0)); // полный конструктор Complex(const Complex& other); // конструктор копирования // получение параметров комплексного числа PAR Get. Re() const; PAR Get. Im() const; // перегруженные операторы Complex operator*(const Complex& other) const; Complex& operator=(const Complex& other); Complex operator~() const; };

21 Пример шаблона класса //////////////////////// // оператор сопряжения template <class PAR> Complex<PAR>: : operator~() 21 Пример шаблона класса //////////////////////// // оператор сопряжения template Complex: : operator~() const { return Complex(m_re, -m_im); } //////////////////////// template ostream& operator<< (ostream& out, const Complex& other); //////////////////////// // вывод на экран template ostream& operator<< (ostream& out, const Complex& other) { return (out<<”(“<

22 Инстанцирование шаблона – процесс генерации объявления класса по шаблону и аргументу Complex<int> a(5), 22 Инстанцирование шаблона – процесс генерации объявления класса по шаблону и аргументу Complex a(5), b(3, 3); Complex x(1. 144, -0. 155); См. пример программы

23 Объекты-функции – объекты, у которых перегружен оператор вызова функций operator() Объекты-функции в <functional> 23 Объекты-функции – объекты, у которых перегружен оператор вызова функций operator() Объекты-функции в : n n n plus – сложение minus – вычитание multiplies – умножение divides – деление modulus – деление по модулю negate – отрицание

24 Стандартный объект-функция negate vector<int> v; vector<int>: : iterator it=v. begin(); while(it != v. 24 Стандартный объект-функция negate vector v; vector: : iterator it=v. begin(); while(it != v. end()) { *it = -(*it); it++; } // то же самое с использование объекта-функции negate transform(v. begin(), v. end(), v. begin(), negate()); // вывод на экран copy(v. begin(), v. end(), ostream_iterator(cout, " ")); // чтение из стандартного потока copy(istream_iterator(cin), istream_iterator(), back_inserter(v));

25 Создание объекта-функции Rand template <class PAR> // параметры – тип данных и возвращаемое 25 Создание объекта-функции Rand template // параметры – тип данных и возвращаемое значение оператора () class Rand : public unary_function { PAR m_min, m_max; public: Rand(PAR min, PAR max) : m_min(min), m_max(max) { } void operator() (PAR& i) { i=(PAR)(rand()*(m_max-m_min))/RAND_MAX+m_min; } }; // использование объекта-функции Rand for_each(v. begin(), v. end(), Rand(-10, 10));

26 Преобразование бинарной функции в унарную n Унарная функция – участвует один элемент (отрицание) 26 Преобразование бинарной функции в унарную n Унарная функция – участвует один элемент (отрицание) Бинарная функция – участвуют два элемента (сложение, умножение, . . . ) n Умножение каждого элемента на 2 – как? n transform(v. begin(), v. end(), v. begin(), multiplies()); n Функция binder 2 nd – преобразует бинарную функцию в унарную, и принимает второй аргумент как параметр бинарной функции () // умножение каждого элемента на 2 transform (v. begin(), v. end(), v. begin(), bind 2 nd(multiplies(), 2)); См. пример программы

27 Предикаты позволяют без изменения шаблона изменять критерии сравнения элементов контейнера и другие подобные 27 Предикаты позволяют без изменения шаблона изменять критерии сравнения элементов контейнера и другие подобные действия. n объект-функция возвращает значение bool Объекты-функции в n n n n n equal_to бинарный предикат равенства not_equal_to бинарный предикат неравенства greater бинарный предикат > less бинарный предикат < (используется по умолчанию) greater_equal бинарный предикат >= less_equal бинарный предикат <= logical_and бинарный предикат И logical_or бинарный предикат ИЛИ logical_not унарный предикат НЕ

28 Стандартный объект-функция greater void main() { vector<int> v(10); for_each(v. begin(), v. end(), Rand<int>(-5, 28 Стандартный объект-функция greater void main() { vector v(10); for_each(v. begin(), v. end(), Rand(-5, 5)); // sort(v. begin(), v. end()); // reverse(v. begin(), v. end()); // сортировка в порядке убывания sort(v. begin(), v. end(), greater()); }

29 Создание предиката In. Range // параметры – тип данных и возвращаемое значение оператора 29 Создание предиката In. Range // параметры – тип данных и возвращаемое значение оператора () class In. Range : public unary_function { int m_left, m_right; public: In. Range(int left, int right) : m_left(left), m_right(right) {} bool operator() (const int& i) { return (i>m_left && i v(10); for_each(v. begin(), v. end(), Rand(0, 10000)); cout << count_if(v. begin(), v. end(), In. Range(1000, 10000)); См. пример программы