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

Презентация:



Advertisements
Похожие презентации
1 Переопределение операций Макаревич Л. Г.. 2 Зачем нужна перегрузка операций? class Complex { double re; double im; public: Complex(double r=0, double.
Advertisements

Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Статические поля класса Статические поля хранят данные, общие для всех элементов класса. Статическое поле существует в единственном экземпляре для всех.
Инструкции C++ Условная инструкция Формат: if (условие) оператор; else оператор; Пример: if (i!=0) { if (j) j++; if(k) k++; else if(p) k--; } else i--;
Учебный курс Объектно-ориентированный анализ и программирование Лекция 7 Методы как средство реализации операций Лекции читает кандидат технических наук.
Информационные технологии Операция присваивания 2 year=2012; i=i+1;
Лекция 13. Введение в ООП. Часть 4 Красс Александр СПбГУ ИТМО, 2008.
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
©ρŧą Базовые конструкции языка.
Разработка на CUDA с использованием Thrust Михаил Смирнов.
Потоки Язык C++ не обеспечивает средств для ввода/вывода Ему это и не нужно; такие средства легко и элегантно можно создать с помощью самого языка Традиционно.
Обработка исключений Основы метапрограммированияОбработка исключений Основы метапрограммирования.
Прикладное программирование кафедра прикладной и компьютерной оптики Наследование.
ОБЪЕКТНО- ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ (ООП) 1.
Прикладное программирование кафедра прикладной и компьютерной оптики Абстрактные типы данных.
САОД кафедра ОСУ 1 Основные абстрактные типы данных Схема процесса создания программ для решения прикладных задач ВУ.
ООП Классы – 2.
Синтаксис языка Java. Символы и синтаксис Перевод строчки эквивалентен пробелу Регистр в именах различается.
УКАЗАТЕЛИ. Переменная - это именованная область памяти с заданным типом. [=значение]; int a; //Переменная типа integer с именем a int b=2;// Переменная.
Лекция 9 Функции. Массивы-параметры функции Передача массива в функцию Пример: void array_enter(int a[], int size) { int i; for (i = 0; i < size; i++)
Транксрипт:

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

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

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

5 Преобразование типов при помощи конструктора // преобразование из double в Complex 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 Аргументы функции по умолчанию описание полного конструктора с параметрами по умолчанию Lens(double r1, double r2, double D=0., double d=0., double n=1.); реализация полного конструктора с параметрами по умолчанию Lens::Lens(double r1, double r2, double D, double d, double n) : m_r1(r1), m_r2(r2), m_d(d), m_D(D), m_n(n) { } аргументы по умолчанию должны быть указаны в конце списка аргументов и подряд Lens lens(100.,-100.); // r1=100 r2=-100 D=0 d=0 n=1 Lens lens(100.,-100.,50.); // r1=100 r2=-100 D=50 d=0 n=1 Lens lens(100.,-100.,50.,10.); // r1=100 r2=-100 D=50 d=10 n=1 Lens lens(100.,-100.,50.,10.,1.5);// r1=100 r2=-100 D=0 d=10 n=1.5 Lens lens(100.,-100.,1.5); // r1=100 r2=-100 D=1.5 d=0 n=1

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

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

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

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 Перегрузка оператора присваивания Правила перегрузки оператора присваивания аргументом должна быть неизменяемая ссылка на экземпляр данного класса перед присваиванием необходимо сделать проверку на присваивание самому себе присваивание должно быть поэлементное оператор должен возвращать ссылку на самого себя // оператор присваивания 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 Перегрузка операторов с присваиванием Правила перегрузки с присваиванием аргументом должна быть неизменяемая ссылка на экземпляр данного класса оператор должен возвращать ссылку на самого себя // умножение с присваиванием 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() 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) { return (p[i][j]); // или p[i*size+j]; } // пример использования matrix x; double y; y=matrix(1,1); // доступ к элементу (1,1)

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

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

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

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

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

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

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

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

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

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 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 Преобразование бинарной функции в унарную Унарная функция – участвует один элемент (отрицание) Бинарная функция – участвуют два элемента (сложение, умножение,...) Умножение каждого элемента на 2 – как? transform(v.begin(), v.end(), v.begin(), multiplies ()); Функция binder2nd – преобразует бинарную функцию в унарную, и принимает второй аргумент как параметр бинарной функции ( ) // умножение каждого элемента на 2 transform (v.begin(), v.end(), v.begin(), bind2nd(multiplies (), 2)); См. пример программы

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

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 Создание предиката InRange // параметры – тип данных и возвращаемое значение оператора () class InRange : public unary_function { int m_left, m_right; public: InRange(int left, int right) : m_left(left), m_right(right) {} bool operator() (const int& i) { return (i>m_left && i