Обобщенное программирование шаблоны классов

10 Лекция. Обобщённое программирование. Шаблоны. Шаблонная функция. Шаблонный класс. Шаблоны: Array, List. DoubleList.

Обобщённое программирование — (англ. generic programming) — такое описании данных и алгоритмов, которое можно применять к различным типам данных, не меняя само это описание.

  • Агентно-ориентированная
  • Компонентно-ориентированная
  • Конкатенативная
  • Декларативная (контрастирует с Императивной)
    • Ограничениями
    • Функциональная
    • Потоком данных
      • Таблично-ориентированная (электронные таблицы)
      • Реактивная
      • Сервис-ориентированная
      • Процедурная
      • Автоматизация процесса программирования
      • Обобщённое программирование
      • Рефлексивно-ориентированная
      • Итерационная
      • Модульная
      • Рекурсивная
      • Объектно-ориентированная
        • Автоматная
        • Разделение ответственности:
          • Аспектно-ориентированная
          • Субъектно-ориентированная

          Метапрограммирование — создание программ, которые порождают другие программы как результат своей работы, либо программ, которые меняют себя во время выполнения.

          Все функции и классы, которые были приводились на лекциях, работали только с одним типом данных (чаще int).

          Шаблоны. Шаблонная функция.

          В языке C++ обобщённое программирование основывается на понятии «шаблон», обозначаемом ключевым словом template.

          int max(int x, int y)  // только для int if (x  y) return y; else return x; > 
          template typename T> // шаблонная функция T max(T x, T y)  if (x  y) return y; else return x; > 

          Применение шаблонной функции..

          1 2 3 4 5 6 7 8 9 10 11 12
          int a = max(10,15); double f = max(123.11, 123.12); max(10,15); max(123.11, 123.12); maxint>(10,15); max double >(123.11, 123.12); 

          Шаблонный класс. Шаблоны: Array, List. DoubleList.

          Перепишем все классы на шаблоны.

          Шаблон Array.

          1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
          // заголовочный файл для Array #ifndef ARRAY_H_ // проверка - не включался ли уже этот файл #define ARRAY_H_ // объявление константы typedef unsigned int size_t; // объявляем новый тип переменных size_t template typename T> // Объявляем шаблонный класс class Array  // объявляем массив private: // модификатор доступа private size_t mySize; // поле - размер массива T *myData; // поле - указатель на массив public: // модификатор доступа public Array(size_t size); // прототип конструктора ~Array(); // прототип деструктора  T set (int i, T val); // прототип метода записи элемента в массив, i- индекс val-значение T get (int i); // прототип метода запроса элемента, i- индекс  size_t getSize(); // прототип метода получения размера массива Array(Array &a); // прототип метода конструктора копий Array& operator=(Array &a); // прототип метода переопределение оператора и копирования массива >; #endif // конец условия
          1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
          // Реализации методов класса Array #include "array.h" template typename T> ArrayT>::Array(size_t size)  // Реализация метода - конструктор mySize = size; // присвоение размера массива полю класса myData = new T [mySize]; // выделение памяти для массива в динамической памяти (куче) > template typename T> ArrayT>::~Array()  // Реализация метода - деструктор delete myData; // освобождение памяти выделенной для массива > template typename T> void ArrayT>::set(int i, T val)  // Реализация метода записи элемента в массив if(i0 || i>(mySize))  // Проверка выхода за рамки массива return -1;  > myData[i]=val; // Запись элемента в массив > template typename T> T ArrayT>::get(int i)  // Реализация метода запроса элемента массива if(i0 || i>(mySize))  // Проверка выхода за рамки массива return -1; > return myData[i]; // Запрос элемента массива > template typename T> size_t ArrayT>::getSize()  // Реализация метода получения размера массива return mySize; // Возвращаем значение поля размера массива >  template typename T> ArrayT>::Array(Array &a)  // Реализация метода конструктора копий mySize = a.mySize; // Копируем значение поля размера массива myData = new T[mySize]; // Выделяем память в куче для нового массива for(int i=0;imySize;i++) // Перебираем элементы массива myData[i]=a.myData[i]; // Копируем элементы массива > > template typename T> ArrayT>& ArrayT>::operator=(Array &a)  // Реализация метода присваивания if(this!=&a)  // Проверяем, чтобы не присвоить массив сам в себя, this указатель на текущий объект в памяти mySize = a.mySize; // Копируем значение поля размера массива delete myData; // Освобождаем память от старого массива myData = new T [mySize]; // Выделяем память в куче для нового массива for(int i=0;imySize;i++) // Перебираем элементы массива myData[i]=a.myData[i]; // Копируем элементы массива > > return *this; // Возвращаем указатель на новый объект > 
          1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
          // Основная программа работы с классом Array #include #include "array.cpp" int main ()  Arrayint> a(100); a.set(13,2345); std::cout<"Размер массива a color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arrayint> b(a); std::cout<"Размер массива b color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arrayint> c(200); std::cout<"Размер массива c color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n"; c=b; std::cout<"Размер массива c color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arrayfloat> fa(100); fa.set(13,23.45); std::cout<"Размер массива a color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arrayfloat> fb(fa); std::cout<"Размер массива b color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arrayfloat> fc(200); std::cout<"Размер массива c color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n"; fc=fb; std::cout<"Размер массива c color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arraychar> ca(100); ca.set(13,'H'); std::cout<"Размер массива a color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arraychar> cb(ca); std::cout<"Размер массива b color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  Arraychar> cc(200); std::cout<"Размер массива c color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n"; cc=cb; std::cout<"Размер массива c color: #339933;">getSize()<"\n"; std::cout<"Элемент массива [13] color: #339933;">get(13)<"\n\n";  >

          Шаблон List.

          1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
          // изменения в классе односвязный список List, чтобы его можно было наследовать template class T>  class List  // объявление класса //private: // модификатор доступа private protected: // модификатор доступа protected, только наследникам, иначе методы наследники не смогут обратиться к полям T myValue; // поле значение List *myNext; // рекурсия, тип поля List, указатель на экземпляр класса public: // модификатор доступа public List(T value)  // конструктор myValue=value; //инициализация поля myValue myNext=0; // инициализация поля myNext > ~List()  // деструктор if(myNext!=0)  // если не дошли до головы списка delete myNext; // освободить буфер в куче > > // метод нужно будет переписать, поэтому разрешить перекрытие этой функции(virtual) virtual void addValue(T value)  // метод добавления элемента в список List *current=this; // сохраняем указатель на текущий экземпляр класса в *current while(current->myNext!=0)  // идем к голове current=current->myNext; // берем следующий указатель > current->myNext=new List(value); // создаем новый экземпляр класса в куче и записываем указатель на него в поле myNext > int length()  // метод получения длины списка int counter=0; // инициализация счетчика for(List *current=this;current!=0;current=current->myNext) // перебираем все элементы списка counter++; // увеличиваем счетчик > return counter; // возвращаем значение счетчика > // метод нужно будет переписать, поэтому разрешить перекрытие этой функции(virtual) virtual void Show()  // метод вывода списка на консоль for(List *current=this;current!=0;current=current->myNext) // перебираем все элементы списка std::cout->myValue<"->"; // выводим значение элемента > std::cout<"0\n"; // выводим голову списка > >;
          1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
          // Основная программа работы с классом DoubleList #include #include "list.cpp" int main()  Listint> L(5); std::cout<"Длина списка "length()<"\n"; L.Show(); L.addValue(6); std::cout<"Длина списка "length()<"\n";  L.Show(); L.addValue(7);  std::cout<"Длина списка "length()<"\n\n";  L.Show(); Listchar> CL('H'); std::cout<"Длина списка "length()<"\n"; CL.Show(); CL.addValue('K'); std::cout<"Длина списка "length()<"\n";  CL.Show(); CL.addValue('F');  std::cout<"Длина списка "length()<"\n";  CL.Show(); >

          Шаблон DoubleList.

          Источник

          Читайте также:  Чья фамилия носит название языка программирования известного математика
Оцените статью