Программирование
<<  Офисное программирование Модульное программирование  >>
Обобщенное программирование
Обобщенное программирование
Что такое обобщенное программирование
Что такое обобщенное программирование
Предпосылки использования
Предпосылки использования
Шаблоны функций
Шаблоны функций
Пример
Пример
Простейший способ решения – перегрузка функций
Простейший способ решения – перегрузка функций
Недостатки
Недостатки
Решение – использование шаблонов функций
Решение – использование шаблонов функций
Ограничения
Ограничения
Пример
Пример
Шаблонные операторы
Шаблонные операторы
Шаблонные операторы
Шаблонные операторы
Класс «счетчик»
Класс «счетчик»
Перегрузка оператора вывода в поток для класса «Счетчик»
Перегрузка оператора вывода в поток для класса «Счетчик»
Перегрузка оператора чтения из потока для класса «Счетчик»
Перегрузка оператора чтения из потока для класса «Счетчик»
Пример использования перегруженных операций ввода-вывода
Пример использования перегруженных операций ввода-вывода
Шаблоны классов
Шаблоны классов
Шаблоны классов
Шаблоны классов
Пример – простейший шаблон массивов произвольной длины
Пример – простейший шаблон массивов произвольной длины
Продолжение
Продолжение
Параметры шаблонов, не являющиеся типами
Параметры шаблонов, не являющиеся типами
Допустимые параметры шаблона, не являющиеся типами
Допустимые параметры шаблона, не являющиеся типами
Пример: класс массивов фиксированной длины
Пример: класс массивов фиксированной длины
Примечания
Примечания
Специализация шаблонов
Специализация шаблонов
Специализация шаблона
Специализация шаблона
Пример – функция maximum
Пример – функция maximum
Совместное использование шаблонных классов и функций
Совместное использование шаблонных классов и функций
Задача
Задача
Класс Comparator, задающий критерий сравнения элементов
Класс Comparator, задающий критерий сравнения элементов
Передача операций как параметров функций
Передача операций как параметров функций
Функция Sort
Функция Sort
Пример использования
Пример использования
Шаблонные методы класса
Шаблонные методы класса
Шаблонные методы класса
Шаблонные методы класса
Исходный код:
Исходный код:
Шаблоны и наследование
Шаблоны и наследование
Использование шаблонов при наследовании
Использование шаблонов при наследовании
Наследование шаблона от простого класса
Наследование шаблона от простого класса
Пример – стек указателей
Пример – стек указателей
Иерархия классов
Иерархия классов
Исходный код
Исходный код
Наследование простых классов от шаблонов
Наследование простых классов от шаблонов
Иерархия классов
Иерархия классов
Исходный код
Исходный код
Пример 2 - иерархия фигур
Пример 2 - иерархия фигур
Реализация без шаблонов
Реализация без шаблонов
Устраняем дублирование кода
Устраняем дублирование кода
Обновленная иерархия
Обновленная иерархия
Обновленная реализация
Обновленная реализация
Преимущества использования шаблонов
Преимущества использования шаблонов
Недостатки использования шаблонов
Недостатки использования шаблонов

Презентация: «Обобщенное программирование». Автор: Aleksey Malov. Файл: «Обобщенное программирование.pptx». Размер zip-архива: 152 КБ.

Обобщенное программирование

содержание презентации «Обобщенное программирование.pptx»
СлайдТекст
1 Обобщенное программирование

Обобщенное программирование

2 Что такое обобщенное программирование

Что такое обобщенное программирование

Парадигма программирования, заключающаяся в написании алгоритмов, которые можно применять к различным типам данных

3 Предпосылки использования

Предпосылки использования

Различные типы данных часто требуется обрабатывать при помощи одних и тех же алгоритмов Сортировка и поиск Контейнеры для произвольного типа элементов Программирование на основе стратегий

4 Шаблоны функций

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

5 Пример

Пример

Требуется разработать семейство функций maximum(a, b), возвращающую значение наибольшего из аргументов a и b Аргументы a и b могут иметь произвольный тип int unsigned int double float

6 Простейший способ решения – перегрузка функций

Простейший способ решения – перегрузка функций

int maximum(int a, int b) { return (a > b) ? a : b; } unsigned int maximum(unsigned int a, unsigned int b) { return (a > b) ? a : b; } float maximum(float a, float b) { return (a > b) ? a : b; } double maximum(double a, double b) { return (a > b) ? a : b; }

7 Недостатки

Недостатки

Тело функции приходится писать несколько раз Усложнение процесса внесения изменений в реализацию функций Ситуация усложняется, если различные экземпляры одной и той же функции разнесены по различным файлам или модулям

8 Решение – использование шаблонов функций

Решение – использование шаблонов функций

Язык C++ имеет языковые средства, позволяющие определить функцию-шаблон, работающую с некоторыми абстрактными типами данных Термин «абстрактный» в данном случае не связан с наследованием, а обозначает некоторый тип данных Шаблон задает поведение целого семейства функций и может быть в дальнейшем использован с некоторыми конкретными типами данных Шаблонные функции широко используются для реализации алгоритмов в библиотеке STL

9 Ограничения

Ограничения

Реализация (исходный код) шаблонной функции должна быть доступна из всех единиц компиляции, где она используется

10 Пример

Пример

// Объявляем шаблонную функцию maximum, принимающую // аргументы некоторого типа T template <class T> T maximum(t a, T b) { return (a > b) ? a : b; } int main() { int max1 = maximum(3, 5); float max2 = maximum(-3.7f, 0.35f) double max3 = maximum(1.2, 7.4); std::string max4 = maximum(std::string(“hello"), std::string(“world")); return 0; }

11 Шаблонные операторы

Шаблонные операторы

12 Шаблонные операторы

Шаблонные операторы

Оператор – частный случай функции, и он также может быть шаблонным Пример – разработать для класса «Счетчик» шаблонные операторы << и >> для работы с классами стандартных потоков STL

13 Класс «счетчик»

Класс «счетчик»

Конструктор может быть помечен как явный при помощи ключевого слова explicit , чтобы запретить возможность его неявного вызова в ситуациях, вроде следующих: CCounter counter(20, 5); counter = 10; эквивалентно: CCounter counter(20, 5); counter = CCounter(10, 0);

Class ccounter { public: explicit ccounter(unsigned maxvalue, counter = 0) :m_maxvalue(maxvalue), m_counter(counter){} unsigned getvalue()const{return m_counter;} unsigned getmaxvalue()const{return m_maxvalue;} ccounter& operator++() { ++m_counter; if (m_counter >= m_maxvalue) { m_counter = 0; } return *this; } ccounter const operator++(int) // постфиксная форма инкремента { // создаем копию, выполняем предынкремент и возвращаем копию ccounter tmpcopy(*this); ++*this; return tmpcopy; } private: unsigned m_maxvalue, m_counter; };

14 Перегрузка оператора вывода в поток для класса «Счетчик»

Перегрузка оператора вывода в поток для класса «Счетчик»

// Выводим информацию о счетчике в виде [counter/maxvalue] // в произвольный поток вывода template <class T> std::basic_ostream<t>& operator<<( std::basic_ostream<t>& stream, ccounter const& counter) { stream << "[" << counter.Getvalue() << "/« << counter.Getmaxvalue() << "]"; return stream; }

15 Перегрузка оператора чтения из потока для класса «Счетчик»

Перегрузка оператора чтения из потока для класса «Счетчик»

template <class T> std::basic_istream<T>& operator>>( std::basic_istream<T>& stream, CCounter & counter) { std::streamoff pos = stream.tellg(); unsigned maxValue = 0; unsigned currentValue = 0; if ( (stream.get() == '[') && (stream >> currentValue) && (stream.get() == '/') && (stream >> maxValue) && (stream.get() == ']') ) { counter = CCounter(maxValue, currentValue); return stream; } stream.seekg(pos); stream.setstate(std::ios_base::failbit | stream.rdstate()); return stream; }

16 Пример использования перегруженных операций ввода-вывода

Пример использования перегруженных операций ввода-вывода

#Include <iostream> #include “counter.H” int main(int argc, char* argv[]) { ccounter c(10); // считывает данные о счетчике из стандартного ввода в формате: // [counter/maxvalue] std::cin >> c; // выводит данные о счетчике в стандартный вывод в формате: // [counter/maxvalue] std::cout << c; return 0; }

17 Шаблоны классов

Шаблоны классов

18 Шаблоны классов

Шаблоны классов

Подобно шаблонам функций программисту может понадобиться иметь шаблоны классов Они задают способы построения отдельных классов, подобно тому, как класс задает способ построения отдельных объектов Шаблонные классы широко используются в библиотеках STL и BOOST, например, для реализации контейнеров и умных указателей Исходный код методов шаблонного класса также должен быть доступен из всех единиц компиляции, где он используется

19 Пример – простейший шаблон массивов произвольной длины

Пример – простейший шаблон массивов произвольной длины

template <class T> class CArray { public: CArray(){...} virtual ~CArray(){...} unsigned GetLength()const{...} void Push(T const& item){...} T& operator[](unsigned index){...} T const& operator[](unsigned index)const{...} void Resize(unsigned newSize){...} CArray(CArray const&){...} CArray operator=(CArray const&){...} private: T * m_pItems; unsigned m_size; };

20 Продолжение

Продолжение

int main() { CArray<int> intArray; intArray.Push(3); intArray.Push(4); intArray[0] = 2; intArray.Resize(1); CArray<std::string> stringArray; stringArray.Push("Hello"); stringArray.Push("World"); stringArray[0] = ("Goodbye"); return 0; }

21 Параметры шаблонов, не являющиеся типами

Параметры шаблонов, не являющиеся типами

22 Допустимые параметры шаблона, не являющиеся типами

Допустимые параметры шаблона, не являющиеся типами

В качестве параметров шаблонов могут выступать не только типы данных, но и: Объекты интегрального или перечислимого типа Целые типы Перечислимые типы Тип bool Указатели на объект или указатель на функцию Ссылки на объект или ссылка на функцию Указатели на методы класса

23 Пример: класс массивов фиксированной длины

Пример: класс массивов фиксированной длины

int main(int argc, char * argv[]) { CSimpleArray<std::string, 10> stringArray; try { stringArray[0] = "Hello"; // throws an exception stringArray[10] = "World"; } catch (std::range_error const& e) { std::cout << e.what(); } return 0; }

template <typename T, size_t SIZE> class CSimpleArray { public: CSimpleArray(T const& value = T()) { for (size_t i = 0; i < SIZE; ++i) { m_items[i] = value; } } size_t GetSize()const{return SIZE;} T& operator[](size_t index) { if (index >= SIZE) throw std::range_error("Index is out of range"); return m_items[index]; } T const& operator[](size_t index)const { if (index >= SIZE) throw std::range_error("Index is out of range"); return m_items[index]; } private: T m_items[SIZE]; };

24 Примечания

Примечания

Разработанный класс CSimpleArray при всей своей простоте обладает рядом преимуществ перед обычным массивом При доступе к элементам массива осуществляется проверка индексов Наличие оператора присваивания и конструктора копирования Элементы массива всегда инициализированы значением конструктора по умолчанию для типа T Для встроенных типов происходит инициализация нулем

25 Специализация шаблонов

Специализация шаблонов

26 Специализация шаблона

Специализация шаблона

Наряду с общим шаблоном бывает необходима некоторая специализированная версия этого же шаблона При специализации на основе исходного первичного шаблона реализуется его специализированная версия для некоторых конкретных параметров Типы специализации Полная Конкретизированы все параметры первичного шаблона Частичная Конкретизирована только часть параметров

27 Пример – функция maximum

Пример – функция maximum

// Первичный шаблон функции нахождения максимума template <class T> T maximum(t a, T b) { return (a > b) ? a : b; } // специализация шаблонной функции maximum типом const char* template <> const char* maximum<const char*>(const char * s1, const char *s2) { return (strcmp(s1, s2) > 0) ? s1 : s2; } int main(int argc, char * argv[]) { std::cout << maximum(2, 3) << "\n"; // output: 3 std::cout << maximum("world", "hello") << "\n"; // output: world return 0; }

28 Совместное использование шаблонных классов и функций

Совместное использование шаблонных классов и функций

29 Задача

Задача

Разработать функцию, выполняющую пузырьковую сортировку шаблонных массивов CArray<T> Требования Произвольные критерии сравнения элементов массива Возможность выполнения сортировки по возрастанию и убыванию Возможность упорядочивания объектов по различным параметрам

30 Класс Comparator, задающий критерий сравнения элементов

Класс Comparator, задающий критерий сравнения элементов

Template <class T> class ccomparator { public: bool lessthan(t const& a, T const& b)const { return a < b; } }; // специализация класс ccomparator для сравнения указателей на char template <> class ccomparator<const char *> { public: bool lessthan(const char * const& a, const char * const& b)const { return strcmp(a, b) < 0; } };

31 Передача операций как параметров функций

Передача операций как параметров функций

Операцию сравнения (объект типа CComparator) будем передавать в качестве параметра в шаблонную функцию Sort Это даст возможность использования различных критериев сравнения элементов одного и того же массива Например, сортировать объекты по различным свойствам или менять порядок сортировки на противоположный

32 Функция Sort

Функция Sort

template <class T, class Comp> void sort(CArray<T> & arr, Comp const& comp) { unsigned n = arr.GetLength(); for (unsigned i = 0; i < n - 1; i++) { for (unsigned j = n - 1; i < j; j--) { if (comp.LessThan(arr[j], arr[j-1])) { T temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; } } } }

33 Пример использования

Пример использования

Template <class T> class ccomparator2 { public: bool lessthan(t const& a, T const& b) const { return a > b; } }; int main() { carray<double> doublearray; doublearray.Push(3.8); doublearray.Push(5.1); // сортируем массив по убыванию элементов sort(doublearray, ccomparator2<double>()); assert(doublearray[0] == 5.1); assert(doublearray[1] == 3.8); return 0; }

34 Шаблонные методы класса

Шаблонные методы класса

35 Шаблонные методы класса

Шаблонные методы класса

В любом классе (в том числе и шаблонном) можно объявить метод-шаблон Пример: В классе CSimpleArray можно реализовать шаблонный оператор присваивания, позволяющий присваивать массивы разных типов и длины

36 Исходный код:

Исходный код:

Template <typename T, size_t SIZE> class csimplearray { public: ... template <class T1, size_t SIZE1> csimplearray<t, SIZE> & operator=(const csimplearray<t1, SIZE1> & other) { if ((void*)this != (void*)&other) // защита от самоприсваивания { size_t const minsize = (SIZE < SIZE1) ? SIZE : SIZE1; for (size_t i = 0; i < minsize; ++i) { m_items[i] = static_cast<t const&>(other[i]); } // заполняем остаток массива (при его наличии) значениями по умолчанию for (size_t i = SIZE1; i < SIZE; ++i) { m_items[i] = T(); } } return *this; } ... }

int main(int argc, char * argv[]) { CSimpleArray<double, 8> doubleArray; CSimpleArray<int, 5> intArray(7); doubleArray = intArray; return 0; }

37 Шаблоны и наследование

Шаблоны и наследование

38 Использование шаблонов при наследовании

Использование шаблонов при наследовании

Ограничений на использование шаблонов при наследовании нет: Шаблон унаследован от простого класса Простой класс унаследован от шаблона Шаблон унаследован от шаблона С помощью шаблонов можно создавать полные или частичные реализации некоторых интерфейсов В этом случае шаблонный параметр выступает в качестве родительского класса Сам шаблонный класс при этом используется как основа для создания конкретных классов

39 Наследование шаблона от простого класса

Наследование шаблона от простого класса

Данный тип наследования позволяет решить проблему «разбухания» кода при инстанцировании шаблонов В этом случае в базовый класс выносится «тяжелая» реализация, которой «облегченный» таким образом шаблонный класс делегирует выполнение своих методов

40 Пример – стек указателей

Пример – стек указателей

Указатели на разные типы данных хранятся в памяти одинаковым образом Исключение – указатели на члены класса Для каждого типа указателей, используемого в программе будет создана (инстанциирована) своя версия класса CStack Разбухание двоичного кода Решение проблемы – специализация шаблонов и наследование от полной специализации класса CStack для указателей типа void*

41 Иерархия классов

Иерархия классов

42 Исходный код

Исходный код

// Первичный шаблон template <typename T> class cstack { public: void push(t const& t) {…} T gettop()const{…} void pop(){…} bool isempty(){…} private: … }; // полная специализация шаблона // для указателей на void template <> class cstack<void*> { public: void push(void * p){…} void * gettop()const{…} void pop(){} bool isempty()const{} };

// Частичная специализация шаблона для // произвольных указателей template <typename T> class cstack<t*> : private cstack<void*> { private: typedef cstack<void*> cbase; public: void push(t * p) { cbase::push(p); } T * gettop()const { return static_cast<t*>(cbase::gettop()); } void pop() { cbase::pop(); } bool isempty()const { return cbase::isempty(); } };

43 Наследование простых классов от шаблонов

Наследование простых классов от шаблонов

Задача – подсчет количества существующих экземпляров объектов некоторых классов Решение: Создать базовый шаблонный класс, конструкторы (по умолчанию и копирования) и деструктор которого осуществляют инкремент/декремент счетчика В качестве параметра шаблона будет выступать класс, для которого необходимо вести подсчет экземпляров Классы, для которых необходимо вести учет количества экземпляров публично наследуются от класса-счетчика

44 Иерархия классов

Иерархия классов

45 Исходный код

Исходный код

template <class T> class CCountable { public: static size_t GetInstanceCount() { return m_counter; } protected: CCountable() { ++m_counter; } CCountable(CCountable const& other) { ++m_counter; } ~CCountable() { --m_counter; } private: static size_t m_counter; }; template<class T> size_t CCountable<T>::m_counter = 0;

class CSomeClass : public CCountable<CSomeClass> { public: }; int main(int argc, char* argv[]) { CSomeClass someObject; std::cout << CSomeClass::GetInstanceCount() << "\n"; { CSomeClass someOtherObject; std::cout << CSomeClass::GetInstanceCount() << "\n"; } std::cout << CSomeClass::GetInstanceCount() << "\n"; return 0; }

Output: 1 2 1

46 Пример 2 - иерархия фигур

Пример 2 - иерархия фигур

Свойства: Цвет Площадь

47 Реализация без шаблонов

Реализация без шаблонов

class Color {…}; class IShape { public: virtual Color GetColor()const=0 virtual void SetColor(Color const& c)=0; virtual double GetArea()const=0; };

class IRectangle : public IShape { … }; class ICircle : public IShape { … };

class CCircle : public ICircle { public: … virtual Color GetColor()const { return m_color; } virtual Color SetColor(Color const& c) { m_color = c; } virtual GetArea()const { return PI * m_radius * m_radius; } private: Color m_color; double m_radius; };

class CRectangle: public IRectangle { public: … virtual Color GetColor()const { return m_color; } virtual Color SetColor(Color const& c) { m_color = c; } virtual GetArea()const { return m_width * m_height; } private: Color m_color; double m_width, m_height; };

48 Устраняем дублирование кода

Устраняем дублирование кода

Создаем абстрактный шаблонный класс CShapeImpl, реализующий виртуальные функции для установки и получения цвета В качестве параметра шаблона будет выступать базовый класс: template <class Base> class CShapeImpl : public Base {…}; Класс является абстрактным, т.к. класс не реализует метод вычисления площади Класс CCircle и CRectangle наследуются от CShapeImpl В качестве шаблонного параметра выступают интерфейсы IСircle и IRectangle соответственно: class CCircle : public CShapeImpl<ICircle> {…};

49 Обновленная иерархия

Обновленная иерархия

50 Обновленная реализация

Обновленная реализация

class Color {…}; class IShape { public: virtual Color GetColor()const=0 virtual void SetColor(Color const& c)=0; virtual double GetArea()const=0; };

class IRectangle : public IShape { … }; class ICircle : public Ishape { … };

template <class Base> class CShapeImpl : public Base { public: … virtual Color GetColor()const { return m_color; } virtual Color SetColor(Color const& c) { m_color = c; } private: Color m_color; };

class CRectangle: public CShapeImpl<IRectangle> { public: virtual GetArea()const { return m_width * m_height; } private: double m_width, m_height; }; class CCircle: public CShapeImpl<ICircle> { public: virtual GetArea()const { return PI * m_radius * m_radius; } private: double m_radius; };

51 Преимущества использования шаблонов

Преимущества использования шаблонов

Повторное использование кода Меньше ручной работы Обобщенные контейнеры и алгоритмы Умные указатели Возможность использования шаблонных реализаций интерфейсов при построении иерархий наследования

52 Недостатки использования шаблонов

Недостатки использования шаблонов

Раздувание бинарного кода При использовании шаблонных функций и классов компилятор генерирует код на этапе компиляции для всех использованных с данным шаблоном типов данных Увеличение времени компиляции Не все распространенные компиляторы поддерживают шаблоны в полной мере Код, содержащий шаблоны сложнее анализировать Сложность анализа сообщений компилятора об ошибках компиляции

«Обобщенное программирование»
http://900igr.net/prezentacija/informatika/obobschennoe-programmirovanie-191045.html
cсылка на страницу
Урок

Информатика

130 тем
Слайды
900igr.net > Презентации по информатике > Программирование > Обобщенное программирование