Бублик Володимир Васильович Об'єктно-орієнтоване програмування Частина 1. Об'єктне програмування. Лекція 8. Параметризовані класи Лекції для студентів 2 курсу Lüneburg
Повторення. Шаблони функцій Звичайна функція: скільки типів, стільки функцій Перепрограмування void swap(int &x, int &y) { int z=x; x=y; y=z; } void swap(Complex &x, Complex &y) {Complex z=x; x=y; y=z; } Узагальнена функція: компілятор генерує функцію потрібного типу за єдиним шаблоном template void swap(Type &x, Type &y) {Type z=x; x=y; y=z; } © Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 2
Шаблон з бібліотеки STL // TEMPLATE FUNCTION swap (from ) template inline void swap(_Ty& _Left, _Ty& _Right) {// exchange values stored at _Left and _Right if (&_Left != &_Right) {// different, worth swapping _Ty _Tmp = _Left; _Left = _Right; _Right = _Tmp; } © Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 3
Конкретизація шаблону Виклик узагальненої функції int i= 1, k=2; swap(i,k); Конкретизується викликом коду, згенерованого за шаблоном AE lea eax,[ebp-78h] B1 push eax B2 lea ecx,[ebp-6Ch] B5 push ecx B6 call std::swap (40A090h) Так само: std:: swap © Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 4
Reuse Шаблони забезпечують нові застосування (reuse) вхідного коду Коли програмувалася бібліотека std її автори не знали про існування в курсі ООП класу Triangle, але шаблон swap допускає конкретизацію довільним типом, для якого існує присвоєння Зауваження. Конкретизація шаблону swap контейнерним класом може виявитися недопустимою © Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 5
6 Вектори стандартного розміру class WrappedVector { private: static const size_t _n; double * _v; public: explicit WrappedVector(); ~ WrappedVector(); size_t size() const { return _n;} double operator[](size_t) const; double& operator[](size_t); };
Питання Як в одній програмі мати вектори кількох стандартних розмірів, наприклад, 10 і 100? Перепрограмуванням class WrappedVector10 { ……………….. }; const size_t WrappedVector10::_n=10; class WrappedVector100 { ……………….. }; const size_t WrappedVector100::_n=100; © Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 7
8 Вектори довільного розміру class DissimilarVector { private: const size_t _n; double * _v; public: explicit DissimilarVector(int); ~DissimilarVector(); size_t size() const { return _n;} double operator[](size_t) const; double& operator[](size_t); };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 9 Типізація векторів Чи це правильно, що вектори різного розміру мають один і той же тип DissimilarVector? DissimilarVector u(10), v(100); Дивлячись, які операції над ними виконувати. Як визначити присвоєння (const size_t _n;)? Як коректно визначити покомпонентні операції, наприклад, додавання векторів так, щоб вона застосовувалася лише до векторів однієї розмірності? u = v; u + v?
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 10 Параметризація векторів Як зробити розмірність частиною типу вектора? Vector10 u; Vector100 v; Підказка: порівняйте з конкретизацією шаблона функції swap (i,k); swap (z1, z2); swap (s1, s2); Вихід: Зробити тип вектора шаблоном, залежним від розмірності як параметру Vector u; Vector v;
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 11 Параметризований вектор template //параметр class Vector { private: const size_t _n; double _v [size]; public: explicit Vector(); ~Vector(); double operator[](int i) const; double& operator[](int i); };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 12 Порівняння типів векторів Тип WrappedVector: Всі вектори в програмі мають одну розмірність не можна оперувати векторами різних розмірностей Тип DissimilarVector Вектори одного типу мають довільну розмірність неможливо виконувати статичний контроль типів Параметризований тип Vector Тип вектора визначається його розмірністю
Конкретизація шаблона класу За єдиним визначенням вхідною мовою template //параметр class Vector; Vector u; компілятором генерується свій об'єктний код для кожного виклику при своєму значенні параметру шаблона u[i]; push i lea ecx,[ebp-18h] A call Vector ::operator[] (409610h) © Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 13
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 14 Діаграми векторів Vector u; Vector v;
Узагальнений метод Кожен метод кодується у вигляді шаблону один раз //Шаблон оператора індексування template double& Vector ::operator[] (size_t index) { return _v[index]; } © Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 15
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 16 Узагальнена утиліта //Шаблон операції скалярного множення template double operator* (const Vector & u, const Vector & v) { double res=0; for (int i=0;i<u.volume(); i++) res += u[i]*v[i]; return res; }
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 17 Статичний контроль типів Vector u1, u2; Vector v1, v2; //Конкретизація для Vector u1*u2; //Конкретизація для Vector v1*v2; //Синтаксична помилка u1*v1;
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 18 Заголовний файл (1) template class Vector { private: const size_t _n; double _v [size]; public: Vector(); ~Vector(); double operator[](int i) const; double& operator[](int i);
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 19 Заголовний файл (2) Vector& operator=(const Vector&); int volume() const { return _n;} }; template ostream& operator<< (ostream&, const Vector &); template istream& operator>> (istream&, Vector &); template bool operator== (const Vector &, const Vector &);
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 20 Заголовний файл (3) template Vector ::Vector(): _n (size) { for (int i=0; i<_n; i++) _v[i] = 0; return; } template Vector ::~Vector() { return; }
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 21 Заголовний файл (4) template Vector & Vector :: operator=(const Vector & vec) { if (this==&vec) return *this; for (int i=0; i<_n; i++) _v[i] = vec._v[i]; return *this; }
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 22 Заголовний файл (5) template ostream& operator<< (ostream& os, const Vector & u) { os<<['<<u.volume()<<]'<<endl<<(; for (int i=0; i<u.volume(); i++) { os<<u[i]<< ; } os<<')'<<endl; return os; }
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 23 Моделі компіляції Параметризовані класи (class templates) компілюються в особливий спосіб компіляція приєднанням (compilation by including) реалізація класу розміщується в заголовному файлі відокремлена компіляція (compilation by separation) реалізація експортується (розповсюдженими компіляторами поки що не підтримується) export class
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 24 Компіляція Компіляція параметризованого класу відбувається мірою визначення об'єктів і використання методів #include Vector.h //Конкретизується клас Vector //Компілюються конструктор і деструктор Vector u; //Компілюється утиліта вводу cin>>u;
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 25 Компіляція Для кожної нової конкретизації створюється власна реалізація //Конкретизується клас Vector //Компілюються його конструктор і деструктор Vector v; //Компілюється утиліта вводу вектора Vector cin>>v;
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 26 Вправа Спроектувати і реалізувати параметризований клас // Текстовий екран розміром //height х width // template class Screen { public: …………………………………………………………………………… };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 27 Діаграма екранів
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 28 Повторення. Різнотипні масиви Фрагменти реалізації масивів елементів різних типів Масив цілих чиселМасив символівМасив точок // Масив елементів типу int ArrayOfInt::ArrayOfIn t (size_t sz): _size(sz), _pElem (new int[_size]) { return; } int& ArrayOfInt::operator[ ] (size_t index) { return _pElem[index]; } // Масив елементів типу char ArrayOfChar::ArrayOfCh ar (size_t sz): _size(sz), _pElem (new char[_size]) { return; } char& ArrayOfChar::operator[ ] (size_t index) { return _pElem[index]; } // Масив елементів типу Point ArrayOfPoint::ArrayOfP oint (size_t sz): _size(sz), _pElem (new Point[_size]) { return; } Point& ArrayOfPoint::operator [] (size_t index) { return _pElem[index]; }
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 29 Визначення типів #include Point.h typedef Point Elem; class Array { private: size_t _size; Elem * _pElem; ………………………. };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 30 Визначення типів Перевага: програмний код не залежить від конкретного типу Недолік: В області видимості конкретного визначення типу typedef неможливо одночасно застосувати інший тип: як в одній програмі одночасно вживати масив точок і масив трикутників?
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 31 Параметризація типовим параметром //Типовий параметр template class Array { private: size_t _size; Elem * _pElem; ………………………. };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 32 Замовчувані значення типових параметрів //Типовий параметр template class Array { private: size_t _size; Elem * _pElem; ………………………. };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 33 Діаграми масивів
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 34 Reuse Програмуємо і використовуємо три класи ArrayOfInt ai(10); ArrayOfChar ac(100); ArrayOfPoint ap(20); Програмуємо один клас і використовуємо скільки завгодно конкретизацій Array<> ad(10); Array ai(20); Array ac(100); Array ap(30);
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 35 Поліпараметризовані класи template class Vector;
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 36 Масив з двома параметрами template //Масив з size елементів типу Elem class Array { public: explicit Array (); ~Array(); private: size_t _size; Elem _pElem[size]; };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 37 Реалізація template Array ::Array ():_size(size) { #ifndef NDEBUG cout<<"Array created ("<<_size<<')'<<endl; #endif return; }
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 38 Вкладені (параметризовані) типи template // Масив елементів типу Elem class Array { public: //Клас для обробки помилкових ситуацій //теж залежить від параметру Elem, //він вкладений, а тому теж параметризований тип class BadArray ……………….
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 39 Вкладені (параметризовані) типи template // Масив елементів типу Elem class Array { public: //Клас для обробки помилкових ситуацій //тепер залежить від двох параметрів size і Elem, //він вкладений, а тому теж параметризований тип class BadArray ……………….
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 40 Діаграми вкладених типів
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 41 Клонування вкладених типів catch (Array ::BadArray x) { cerr<<"Non-existing symbol"<<endl; cerr<<x; } catch (Array ::BadArray x) { cerr<<"Non-existing real"<<endl; cerr<<x; }
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 42 Реалізація вкладених типів template class Array ::BadArray { private: string _reason; size_t _index; public: BadArray(string reason="", size_t index=0); ~BadArray(); const string& getReason() const; };
© Бублик В.В. ООП-1. Об'єктне програмування. Лекція 8. Параметризовані класи 43 Висновки Одне з найважливіших застосувань параметризованих типів узагальнене програмування контейнерів STL стандартна бібліотека шаблонів (Standard Template Library) Параметризовані контейнери (на практичних) Послідовність Список Стек Черга Дек