08 Templates

679 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
679
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

08 Templates

  1. 1. Бублик Володимир Васильович Програмування - 2 Лекція 8 . Об'єктне програмування. Параметризовані класи Лекції для студентів 2 курсу
  2. 2. Повторення <ul><li>class DissimilarVector </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>const size_t _n; </li></ul><ul><li>double * _v; </li></ul><ul><li>public : </li></ul><ul><li>explicit DissimilarVector(int); </li></ul><ul><li>~DissimilarVector(); </li></ul><ul><li>size_t size() const { return _n;} </li></ul><ul><li>double operator [](size_t) const ; </li></ul><ul><li>double & operator [](size_t); </li></ul><ul><li>}; </li></ul>
  3. 3. Типізація векторів <ul><li>DissimilarVector u(10), v(100); </li></ul><ul><li>Об'єкти u і v мають один і той же тип DissimilarVector </li></ul><ul><li>Розмірності векторів u і v визначені статично, але їх типи не розрізняються </li></ul><ul><li>Як визначити додавання векторів u і v? </li></ul><ul><li>Як включити статичну розмірність до типу вектора? </li></ul><ul><li>Вихід : Зробити тип вектора залежним від розмірності як параметру </li></ul>
  4. 4. Параметризований вектор <ul><li>template <size_t size > // параметр </li></ul><ul><li>class Vector </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>const size_t _n; </li></ul><ul><li>double _v [ size ]; </li></ul><ul><li>public : </li></ul><ul><li>explicit Vector(); </li></ul><ul><li>~Vector(); </li></ul><ul><li>double operator []( int i) const ; </li></ul><ul><li>double & operator []( int i ); </li></ul><ul><li>}; </li></ul>
  5. 5. Діаграми векторів <ul><li>Vector <10> v ; </li></ul><ul><li>Vector <100> w ; </li></ul>
  6. 6. Порівняння типів векторів <ul><li>Тип WrappedVector : </li></ul><ul><li>Всі вектори в програмі мають одну розмірність ― не можна оперувати векторами різних розмірностей </li></ul><ul><li>Тип DissimilarVector </li></ul><ul><li>Вектори одного типу мають довільну розмірність ― неможливо виконувати статичний контрольтипів </li></ul><ul><li>Параметризований тип Vector </li></ul><ul><li>Тип вектора визначається його розмірністю </li></ul>
  7. 7. Узагальнена операція <ul><li>// Скалярне множення параметризованих векторів </li></ul><ul><li>template <size_t size> </li></ul><ul><li>double operator * </li></ul><ul><li>( const Vector<size>& u, const Vector<size>& v) </li></ul><ul><li>{ </li></ul><ul><li>double res=0; </li></ul><ul><li>for ( int i=0;i<u.volume(); i++) </li></ul><ul><li>res += u[i]*v[i]; </li></ul><ul><li>return res; </li></ul><ul><li>} </li></ul>
  8. 8. Статичний контроль типів <ul><li>Vector<10> u1, u2; </li></ul><ul><li>Vector<100> v1, v2; </li></ul><ul><li>// Конкретизація для Vector<10> </li></ul><ul><li>u1*u2; </li></ul><ul><li>// Конкретизація для Vector<100> </li></ul><ul><li>v1*v2; </li></ul><ul><li>// Синтаксична помилка </li></ul><ul><li>u1*v1; </li></ul>
  9. 9. Заголовний файл (1) <ul><li>template <size_t size > </li></ul><ul><li>class Vector </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>const size_t _n; </li></ul><ul><li>double _v [ size ]; </li></ul><ul><li>public : </li></ul><ul><li>explicit Vector(); </li></ul><ul><li>~Vector(); </li></ul><ul><li>double operator []( int i) const ; </li></ul><ul><li>double & operator []( int i ); </li></ul>
  10. 10. Заголовний файл (2) <ul><li>Vector& operator =( const Vector&); </li></ul><ul><li>int volume() const { return _n; } </li></ul><ul><li>}; </li></ul><ul><li>template <size_t size>ostream& operator << </li></ul><ul><li>(ostream&, const Vector<size>&); </li></ul><ul><li>template <size_t size> istream& operator >> </li></ul><ul><li>(istream&, Vector<size>&); </li></ul><ul><li>template <size_t size> bool operator == </li></ul><ul><li>( const Vector<size>&, const Vector<size>&); </li></ul>
  11. 11. Заголовний файл (3) <ul><li>template < int size> Vector<size>::Vector(): _n (size) </li></ul><ul><li>{ </li></ul><ul><li>for ( int i=0; i<_n; i++) </li></ul><ul><li>_v[i] = 0; </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul><ul><li>template <int size> </li></ul><ul><li>Vector<size>::~Vector() </li></ul><ul><li>{ </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  12. 12. Заголовний файл (4) <ul><li>template < int size> </li></ul><ul><li>Vector<size>& Vector<size>:: </li></ul><ul><li>operator =( const Vector<size>& vec) </li></ul><ul><li>{ </li></ul><ul><li>if ( this ==&vec) </li></ul><ul><li>return * this ; </li></ul><ul><li>for ( int i=0; i<_n; i++) </li></ul><ul><li>_v[i] = vec._v[i]; </li></ul><ul><li>return * this ; </li></ul><ul><li>} </li></ul>
  13. 13. Заголовний файл (5) <ul><li>template <size_t size> ostream& operator << </li></ul><ul><li>(ostream& os, const Vector<size>& u) </li></ul><ul><li>{ </li></ul><ul><li>os<<‘ [ '<<u.volume()<<‘ ] '<<endl <<‘(‘ ; </li></ul><ul><li>for ( int i=0; i<u.volume(); i++) </li></ul><ul><li>{ </li></ul><ul><li>os<<u[i] <<‘ ‘ ; </li></ul><ul><li>} </li></ul><ul><li>os<<')'<<endl; </li></ul><ul><li>return os; </li></ul><ul><li>} </li></ul>
  14. 14. Моделі компіляції <ul><li>Параметризовані класи ( class templates ) компілюються в особливий спосіб </li></ul><ul><li>компіляція приєднанням ( compilation by including ) реалізація класу розміщується в заголовному файлі </li></ul><ul><li>відокремлена компіляція ( compilation by separation ) реалізація експортується (розповсюдженими компіляторами поки що не підтримується) export class </li></ul>
  15. 15. Компіляція <ul><li>Компіляція параметризованого класу відбувається мірою визначення об'єктів і використання методів </li></ul><ul><li>// Конкретизується клас Vector<10> </li></ul><ul><li>// Компілюються конструктор і деструктор </li></ul><ul><li>Vector<10> u; </li></ul><ul><li>// Компілюється утиліта вводу </li></ul><ul><li>cin>>u; </li></ul>
  16. 16. Компіляція <ul><li>Для кожної нової конкретизації створюється власна реалізація </li></ul><ul><li>// Конкретизується клас Vector<10 0 > </li></ul><ul><li>// Компілюються його конструктор і деструктор </li></ul><ul><li>Vector<10 0 > v; </li></ul><ul><li>// Компілюється утиліта вводу вектора Vector<10 0 > </li></ul><ul><li>cin>>v; </li></ul>
  17. 17. Вправа <ul><li>Спроектувати і реалізувати параметризований клас </li></ul><ul><li>// Текстовий екран розміром </li></ul><ul><li>// height х width </li></ul><ul><li>// </li></ul><ul><li>template < int height, int width> </li></ul><ul><li>class Screen </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>…………………………………………………………………………… </li></ul>
  18. 18. Діаграма класів
  19. 19. Повторення. Різнотипні масиви // Масив елементів типу Point ArrayOfPoint ::ArrayOfPoint (size_t sz): _size(sz), _pElem ( new Point[_size]) { return ; } Point& ArrayOfPoint:: operator [] (size_t index) { return _pElem[index]; } // Масив елементів типу char ArrayOfChar ::ArrayOfChar (size_t sz): _size(sz), _pElem ( new char [_size]) { return ; } char & ArrayOfChar:: operator [] (size_t index) { return _pElem[index]; } // Масив елементів типу int ArrayOfInt ::ArrayOfInt (size_t sz): _size(sz), _pElem ( new int [_size]) { return ; } int & ArrayOfInt:: operator [] (size_t index) { return _pElem[index]; } Масив точок Масив символів Масив цілих чисел Фрагменти реалізації масивів елементів різних типів
  20. 20. Визначення типів <ul><li>#include “Point.h” </li></ul><ul><li>typedef Point Elem; </li></ul><ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>size_t _size; </li></ul><ul><li>Elem * _pElem; </li></ul><ul><li>……………………… . </li></ul><ul><li>}; </li></ul>
  21. 21. Визначення типів <ul><li>Перевага : програмний код не залежить від конкретного типу </li></ul><ul><li>Недолік : В області видимості конкретного визначення типу typedef неможливо одночасно застосувати інший тип </li></ul>
  22. 22. Параметризація типовим параметром <ul><li>// Типовий параметр </li></ul><ul><li>template < typename Elem > </li></ul><ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>size_t _size; </li></ul><ul><li>Elem * _pElem; </li></ul><ul><li>……………………… . </li></ul><ul><li>}; </li></ul>
  23. 23. Замовчувані значення типових параметрів <ul><li>// Типовий параметр </li></ul><ul><li>template < typename Elem = double > </li></ul><ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>size_t _size; </li></ul><ul><li>Elem * _pElem; </li></ul><ul><li>……………………… . </li></ul><ul><li>}; </li></ul>
  24. 24. Діаграми масивів
  25. 25. Порівняння <ul><li>Програмуємо і використовуємо три класи </li></ul><ul><li>ArrayOfInt AI ( 10 ) ; </li></ul><ul><li>ArrayOfChar AC ( 10 ) ; </li></ul><ul><li>ArrayOfPoint AP ( 10 ) ; </li></ul><ul><li>Програмуємо один клас і використовуємо скільки завгодно конкретизацій </li></ul><ul><li>Array<> DAI(10); </li></ul><ul><li>Array<int> TAI(10); </li></ul><ul><li>Array<char> TAC(10); </li></ul><ul><li>Array<Point> TAP(10); </li></ul>
  26. 26. Поліпараметризовані класи
  27. 27. Масив з двома параметрами <ul><li>t emplate <size_t size , typename Elem > </li></ul><ul><li>// Масив з size елементів типу Elem </li></ul><ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>explicit Array (); </li></ul><ul><li>~Array(); </li></ul><ul><li>private : </li></ul><ul><li>size_t _size; </li></ul><ul><li>Elem _pElem[ size ]; </li></ul><ul><li>}; </li></ul>
  28. 28. Реалізація <ul><li>template <size_t size, typename Elem> </li></ul><ul><li>Array<size, Elem>::Array ():_size(size) </li></ul><ul><li>{ </li></ul><ul><li>#ifndef NDEBUG </li></ul><ul><li>cout<<&quot;Array created (&quot;<<_size<<')'<<endl; </li></ul><ul><li>#endif </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  29. 29. Вкладені (параметризовані) типи <ul><li>template < typename Elem> </li></ul><ul><li>// Масив елементів типу Elem </li></ul><ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>// Клас для обробки помилкових ситуацій </li></ul><ul><li>// теж залежить від параметру Elem , </li></ul><ul><li>// він вкладений, а тому теж параметризований тип </li></ul><ul><li>class BadArray </li></ul><ul><li>……………… . </li></ul>
  30. 30. Вкладені (параметризовані) типи <ul><li>template <size_t size, typename Elem> </li></ul><ul><li>// Масив елементів типу Elem </li></ul><ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>// Клас для обробки помилкових ситуацій </li></ul><ul><li>// тепер залежить від двох параметрів size і Elem , </li></ul><ul><li>// він вкладений, а тому теж параметризований тип </li></ul><ul><li>class BadArray </li></ul><ul><li>……………… . </li></ul>
  31. 31. Діаграми вкладених типів
  32. 32. Клонування вкладених типів <ul><li>catch (Array< 4 , char >::BadArray x) </li></ul><ul><li>{ </li></ul><ul><li>cerr<<&quot;Non-existing symbol&quot;<<endl; </li></ul><ul><li>cerr<<x; </li></ul><ul><li>} </li></ul><ul><li>catch (Array< 5 , double >::BadArray x) </li></ul><ul><li>{ </li></ul><ul><li>cerr<<&quot;Non-existing real&quot;<<endl; </li></ul><ul><li> cerr<<x; </li></ul><ul><li>} </li></ul>
  33. 33. Реалізація вкладених типів <ul><li>template < size_t size, typename Type> </li></ul><ul><li>class Array< size, Type>::BadArray </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>string _reason; </li></ul><ul><li>size_t _index; </li></ul><ul><li>public : </li></ul><ul><li>BadArray(string reason=&quot;&quot;, size_t index=0) ; </li></ul><ul><li>~BadArray(); </li></ul><ul><li>const string& get Reason() const ; </li></ul><ul><li>}; </li></ul>
  34. 34. Висновки <ul><li>Одне з найважливіших застосувань параметризованих типів ― узагальнене програмування контейнерів </li></ul><ul><li>STL стандартна бібліотека шаблонів ( Standard Template Library ) </li></ul><ul><li>Параметризовані контейнери (на практичних) </li></ul><ul><li>Послідовність </li></ul><ul><li>Список </li></ul><ul><li>Стек </li></ul><ul><li>Черга </li></ul><ul><li>Дек </li></ul>

×