09 Static Polymorphism

718 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
718
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

09 Static Polymorphism

  1. 1. Бублик Володимир Васильович Програмування - 2 Лекція 9. Процедурне програмування. Статичний поліморфізм Лекції для студентів 2 курсу
  2. 2. 1. Функціональна полісемія
  3. 3. Непряме звернення до функцій <ul><li>Оголошення указника функції </li></ul><ul><li>double (* f ) ( double ); </li></ul><ul><li>Визначення з ініціалізацією </li></ul><ul><li>double (*f ) ( double ) = 0; </li></ul><ul><li>double (* trigon) ( double ) = sin; </li></ul><ul><li>Присвоєння </li></ul><ul><li>trigon = cos; </li></ul>
  4. 4. Виклик за указником <ul><li># include <cmath> </li></ul><ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>double (*trigon) ( double ) = sin; </li></ul><ul><li>cout<< trigon (0)<<endl; </li></ul><ul><li>trigon = cos; </li></ul><ul><li>cout<< trigon (0)<<endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  5. 5. Масиви указників функцій <ul><li>const int n = 10; </li></ul><ul><li>double (*g[n]) ( double ); </li></ul><ul><li>typedef double (*F) ( double ); </li></ul><ul><li>F * pf = new F[n]; </li></ul><ul><li>g[1] = sin; </li></ul><ul><li>pf[2] = exp; </li></ul>
  6. 6. Функціонали <ul><li>Розв'язування рівнянь методом ділення навпіл </li></ul><ul><li>R x R x R x [R -> R] -> R </li></ul><ul><li>double Newton ( double a, double b, double eps, </li></ul><ul><li>double (*f) ( double )); </li></ul><ul><li>double Simpson ( double a, double b, double eps, </li></ul><ul><li>double (*f) ( double ) ); </li></ul><ul><li>В яких випадках бажано або необхідно мати одне спільне позначення для різних дій? </li></ul>
  7. 7. 2 . Розширення області визначення ( overloading ) функцій Що бракує С ?
  8. 8. Мінімізація понять <ul><li>На всі випадки один символ для додавання </li></ul><ul><li>Натуральні 1+2 // 1 + n 2 </li></ul><ul><li>Цілі -1+2 // -1 + i 2 </li></ul><ul><li>Раціональні ⅓ + ⅝ // ⅓ + z ⅝ </li></ul><ul><li>Дійсні φ + 2 π k // φ + r 2 π k </li></ul><ul><li>Комплексні (a + b i ) + (c + d i ) // (a ☺ b i ) ☻ (c ☺ d i ) </li></ul><ul><li>Вектори u+v </li></ul><ul><li>Матриці A+B </li></ul>
  9. 9. Однойменні функції <ul><li>Обмін цілих значень </li></ul><ul><li>void pswap ( int *x, int *y) ; // стиль С </li></ul><ul><li>void rswap ( int &x, int &y) ; // стиль С ++ </li></ul><ul><li>Як назвати цю ж функцію для дійсних (символьних, …) значень? </li></ul><ul><li>void pswap_ char ( char *x, char *y) ; //? </li></ul><ul><li>void pswap_ 1 ( char *x, char *y) ; //? </li></ul><ul><li>Краще всього так само pswap або відповідно rswap </li></ul>
  10. 10. Overloading <ul><li>Якщо функція визначається сигнатурою, а не тільки іменем , то кожній сигнатурі приписуємо свою реалізацію </li></ul><ul><li>void pswap ( int *x, int *y) ; </li></ul><ul><li>void pswap ( char *x, char *y) ; </li></ul><ul><li>void pswap ( double *x, double *y) ; </li></ul>
  11. 11. Виклики <ul><li>Якщо функція визначається сигнатурою, а не тільки іменем , то за типами фактичних параметрів можна встановити, функція якої саме сигнатури викликається </li></ul><ul><li>char a, b; </li></ul><ul><li>int m, n; </li></ul><ul><li>float x, y; </li></ul><ul><li>pswap ( &a, &b ) ; </li></ul><ul><li>pswap ( &m, &n ) ; </li></ul><ul><li>pswap ( &x, &y ) ; </li></ul>
  12. 12. Перший висновок <ul><li>Якщо функція визначається сигнатурою, а не тільки іменем , то немає більше необхідності в різних іменах pswap і rswap для функцій swap , що різнитимуться типами параметрів: указниками та відсилками </li></ul><ul><li>void swap ( int &x, int &y); </li></ul><ul><li>void swap ( int *x, int *y); </li></ul><ul><li>Але для сигнатури </li></ul><ul><li>void swap ( int x, int y); </li></ul><ul><li>вже немає місця (чому?) </li></ul>
  13. 13. Функції swap : різні способи передачі параметрів <ul><li>void swap ( int *x, int *y) </li></ul><ul><li>{ </li></ul><ul><li>int z=*x; *x=*y; *y=z; </li></ul><ul><li>return; </li></ul><ul><li>} </li></ul><ul><li>void swap ( int &x, int &y) </li></ul><ul><li>{ </li></ul><ul><li>int z=x; x=y; y=z; </li></ul><ul><li>} </li></ul>
  14. 14. Функції swap : різні типи даних <ul><li>void swap (double *x, double *y) </li></ul><ul><li>{ </li></ul><ul><li>double z=*x; *x=*y; *y=z; </li></ul><ul><li>return; </li></ul><ul><li>} </li></ul><ul><li>void swap (double &x, double &y) </li></ul><ul><li>{ </li></ul><ul><li>double z=x; x=y; y=z; </li></ul><ul><li>} </li></ul>
  15. 15. Функції swap : різні реалізації <ul><li>void swap ( int *x, int *y) </li></ul><ul><li>{ </li></ul><ul><li>*x= * x+*y; *y=*x-*y;*x=*x-*y; </li></ul><ul><li>return; </li></ul><ul><li>} </li></ul><ul><li>void swap ( int &x, int &y) </li></ul><ul><li>{ </li></ul><ul><li>x=x+y; y=x-y; x=x-y; </li></ul><ul><li>} </li></ul>
  16. 16. 3 . Розширення області визначення ( overloading ) опера цій Що ще бракує С ?
  17. 17. Довизначені операції <ul><li>struct Point </li></ul><ul><li>{ </li></ul><ul><li>double _x; </li></ul><ul><li>double _y; </li></ul><ul><li>}; </li></ul><ul><li>const Point plus (Point u, Point v) // дуже незграбно </li></ul><ul><li>{ </li></ul><ul><li>Point res; </li></ul><ul><li>res._x = u._x+v._x; </li></ul><ul><li>res._y = u._y+v._y; </li></ul><ul><li>return res; </li></ul><ul><li>} </li></ul>
  18. 18. Так краще <ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>const Point one_zero = {1, 0}; </li></ul><ul><li>Point u = {2, 3} ; </li></ul><ul><li>Point v = u + one_zero; </li></ul><ul><li>cout<< v._x << v._y<< endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  19. 19. Так ще краще <ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>const Point one = {1, 0}; </li></ul><ul><li>Point u = {2, 3} ; </li></ul><ul><li>Point v = u + one; </li></ul><ul><li>cout << v<< endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  20. 20. Або навіть <ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>const Point one_zero = {1, 0}; </li></ul><ul><li>Point u = {2, 3} ; </li></ul><ul><li>cout << u + one_zero << endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  21. 21. Point.h <ul><li>// Arithmetic </li></ul><ul><li>const Point operator + ( const Point & , const Point & ); </li></ul><ul><li>// Варіація </li></ul><ul><li>// Point operator + (Point , Point); </li></ul><ul><li>// Boolean </li></ul><ul><li>bool operator == ( const Point &, const Point &); </li></ul><ul><li>// Input-output </li></ul><ul><li>ostream& operator <<(ostream &os, const Point &); </li></ul><ul><li>istream& operator >>(istream &is, Point &); </li></ul>
  22. 22. Погодження <ul><li>Замість </li></ul><ul><li>plus (u, v); або operator+(u, v); </li></ul><ul><li>Пишемо </li></ul><ul><li>u+v; </li></ul><ul><li>Відповідно замість суперпозиції </li></ul><ul><li>operator+(u, operator+(v, w)); </li></ul><ul><li>звичайний запис </li></ul><ul><li>u+v+w; </li></ul>
  23. 23. Point.cpp <ul><li>const Point operator +( const Point & u, const Point & v) </li></ul><ul><li>{ </li></ul><ul><li>Point res = {u._x+v._x, u._y+v._y}; </li></ul><ul><li>return res; </li></ul><ul><li>} </li></ul><ul><li>bool operator ==( const Point& u, const Point & v) </li></ul><ul><li>{ </li></ul><ul><li>return (u._x == v._x) && (u._y == v._y); </li></ul><ul><li>} </li></ul>
  24. 24. Point.cpp <ul><li>ostream& operator <<(ostream &os, const Point& u) </li></ul><ul><li>{ </li></ul><ul><li>os<<'('<<u._x<<','<<u._y<<')'; </li></ul><ul><li>return os; </li></ul><ul><li>} </li></ul><ul><li>istream& operator >>(istream &is, Point& u) </li></ul><ul><li>{ </li></ul><ul><li>is>>u._x>>u._y; </li></ul><ul><li>return is; </li></ul><ul><li>} </li></ul>
  25. 25. Змішані типи <ul><li>struct Complex </li></ul><ul><li>{ </li></ul><ul><li>double _re; </li></ul><ul><li>double _im; </li></ul><ul><li>}; </li></ul><ul><li>// Arithmetic </li></ul><ul><li>Complex operator + ( const Complex &, const Complex &); </li></ul><ul><li>Complex operator + ( double , const Complex &); </li></ul><ul><li>Complex operator + (c onst Complex &, double ); </li></ul>
  26. 26. Змішані типи <ul><li>const Complex i = {0, 1}; </li></ul><ul><li>Complex z = {1, 1}; </li></ul><ul><li>double x = 2, y=3; </li></ul><ul><li> cout << ( x +5) + (z + i) + y<<endl; </li></ul><ul><li>Complex operator+ (const Complex &, const Complex &); </li></ul><ul><li>Complex operator+ (double, const Complex &); </li></ul><ul><li>Complex operator+ (const Complex &, double); </li></ul><ul><li>ostream& operator<<(ostream &os, const Complex &); </li></ul><ul><li>Як визначити одне додавання для всіх? (далі буде) </li></ul>
  27. 27. Множення <ul><li>struct WrappedVector </li></ul><ul><li>{ </li></ul><ul><li>static const int n; </li></ul><ul><li>double * x; </li></ul><ul><li>}; </li></ul><ul><li>double operator * ( const WrappedVector&, const WrappedVector&); </li></ul><ul><li>Або ( але не одночасно, чому?) </li></ul><ul><li>const WrappedVector operator * ( const WrappedVector&, const WrappedVector&); </li></ul>
  28. 28. 4 . Узагальнені функції ( function template)
  29. 29. Мінімізація текстів <ul><li>void swap ( int & x, int & y) ; </li></ul><ul><li>void swap ( char & x, char & y) ; </li></ul><ul><li>void swap ( float & x, float & y) ; </li></ul><ul><li>Записати три і більше реалізацій одним текстом </li></ul>
  30. 30. Myswap.h <ul><li>Куди помістити? </li></ul><ul><li>template < typename T> </li></ul><ul><li>void my swap (T &x, T &y) </li></ul><ul><li>{ </li></ul><ul><li>T z = x; x = y; y = z; </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul><ul><li>Чому не Myswap. с pp ? </li></ul>
  31. 31. Myswap.cpp <ul><li>int m=10, n=20; </li></ul><ul><li>myswap (m, n); </li></ul><ul><li>double a=1.25, b = 2.50; </li></ul><ul><li>myswap (a, b); </li></ul><ul><li>Point u ={1,2}, v={3,4}; </li></ul><ul><li>myswap(u,v); </li></ul><ul><li>Complex z1 = {1,1}, z2 = {2,2}; </li></ul><ul><li>myswap (z1, z2); </li></ul>
  32. 32. Конкретизація <ul><li>int m=10, n=20; </li></ul><ul><li>short k=50, i=40; </li></ul><ul><li>myswap<int> (m, n); </li></ul><ul><li>myswap (m, n); </li></ul><ul><li>myswap (i, k); </li></ul><ul><li>// Звичайна функція </li></ul><ul><li>void myswap ( int &x, int &y) </li></ul><ul><li>{ </li></ul><ul><li>cout<<&quot;Non template&quot;<<endl; </li></ul><ul><li>x=x+y; y=x-y; x=x-y; </li></ul><ul><li>} </li></ul>
  33. 33. Союз довизначень і узагальнень <ul><li>Для типу Т повинні бути визначені всі функції і операції, вжиті в узагальненій функції </li></ul><ul><li>template < typename T> </li></ul><ul><li>T max(T x, Ty) </li></ul><ul><li>{ </li></ul><ul><li>return (x>y)?x:y; </li></ul><ul><li>} </li></ul>
  34. 34. Союз довизначень і узагальнень <ul><li>int m=10, n=20; </li></ul><ul><li>cout<<max (m, n) <<endl ; </li></ul><ul><li>double a=1.25, b = 2.50; </li></ul><ul><li>cout<<max (a, b) <<endl ; </li></ul><ul><li>Point u ={1,2}, v={3,4}; </li></ul><ul><li>// max (u,v); ERROR </li></ul><ul><li>Complex z1 = {1,1}, z2 = {2,2}; </li></ul><ul><li>// max (z1, z2); ERROR </li></ul>
  35. 35. Складність компіляції <ul><li>Вибір функції за типами фактичних параметрів з урахуванням можливих перетворень типів, використання замовчуваних значень параметрів, можливостей конкретизації шаблонів. В деяких випадках компілятор не справляється з однозначним визначенням потрібної функції </li></ul>
  36. 36. Висновок <ul><li>Поліморфізм полягає у використанні об'єктів, що можуть набувати багатьох різних типів. </li></ul><ul><li>При динамічному поліморфізмі тип об'єкта визначиться лише на етапі виконання (далі буде). </li></ul><ul><li>Статичний поліморфізм ― це визначення типів, використаних узагальненою функцією, на етапі компіляції з одночасною конкретизацією шаблону або вибором підходящої звичайної функції. Конкретизація можлива, якщо всі вирази шаблону визначені для конкретизуючого типу </li></ul>

×