27
TEMPLATE О СПОСОБЕ НАПИСАНИЯ ПРОГРАММЫ, КОТОРАЯ ВЫПОЛНЯЕТСЯ ВНУТРИ КОМПИЛЯТОРА

Объектно-Ориентированное Программирование на C++, Лекция 6

Embed Size (px)

DESCRIPTION

TEMPLATE О СПОСОБЕ НАПИСАНИЯ ПРОГРАММЫ, КОТОРАЯ ВЫПОЛНЯЕТСЯ ВНУТРИ КОМПИЛЯТОРА

Citation preview

Page 1: Объектно-Ориентированное Программирование на C++, Лекция 6

TEMPLATEО СПОСОБЕ НАПИСАНИЯ ПРОГРАММЫ, КОТОРАЯ ВЫПОЛНЯЕТСЯ ВНУТРИ КОМПИЛЯТОРА

Page 2: Объектно-Ориентированное Программирование на C++, Лекция 6

Два вида многократного использования кода

Наследование

• Создаем структуру для работы с «базовым классом»

• Создаем классы-наследники на каждый случай.

Шаблоны

• Описываем «стратегию работы» с «неопределенным» классом.

• Компилятор в момент создание класса по шаблону, сам создает нужный «код» для конкретного класса.

Page 3: Объектно-Ориентированное Программирование на C++, Лекция 6

TemplatesшаблоныПротечка абстракции: Неудобной составляющей работы с коллекциями объектов родительского типа является необходимость приведения родительского типа к типу-наследнику (для выполнения необходимых операций над элементом коллекции). Т.е. мы жертвуем статическим контролем типов.

Шаблон типа позволяет достаточно просто определить и реализовать без потерь в эффективности выполнения программы и, не отказываясь от статического контроля типов, любые виды коллекций.

Page 4: Объектно-Ориентированное Программирование на C++, Лекция 6

Простой шаблонCPP_Examples14_Templatetemplate <class T> class Print

{

public:

Print(T value)

{

std::cout << "Value:" << value <<

std::endl;

};

};

Перед описанием класса ставим ключевое слово template <class T>

T – используем вместо имени класса, который будет заменяться при создании конкретного экземпляра класса.

Page 5: Объектно-Ориентированное Программирование на C++, Лекция 6

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

template <class T>

class mycontainer {

// …

};

template <>

class mycontainer <char> {

// ..

};

Иногда бывает необходимость сделать специальную реализацию шаблона для какого-либо типа.

В этом случае, можно описать отдельную реализацию класса, дополнив его новыми методами или переопределив реализацию существующих.

Page 6: Объектно-Ориентированное Программирование на C++, Лекция 6

Templatesдве модели1. Наиболее популярный подход - модель включения(inclusion model), определения шаблонов полностью размещаются в заголовочном файле.2. Модель явного инстанцирования (explicitinstantiation model), как правило реализуется директивой явного инстанцирования (explicitinstantiation directive).

Page 7: Объектно-Ориентированное Программирование на C++, Лекция 6

Inclusion modeltemplate<class T> class stack {

T* v;

T* p;

int sz;

public:

stack(int s) { v = p = new T[sz=s]; }

~stack() { delete[] v; }

void push(T a) { *p++ = a; }

T pop() { return *--p; }

int size() const { return p-v; }

};

Page 8: Объектно-Ориентированное Программирование на C++, Лекция 6

explicit instantiation modelCPP_Examples14_TemplateStacktemplate <class T> class

MyStack

{

public:

MyStack(void);

};

template <class T>

MyStack<T>::MyStack(void)

{

_size = 0;

_current = NULL;

}

template class MyStack<class

MyClass>;

Page 9: Объектно-Ориентированное Программирование на C++, Лекция 6

Множественные параметры шаблонов и параметры-переменныеCPP_Examples14_MultiTemplate

template <class A, class B> class Sum

{

};

template <class A, int B> class Add

{

};

• Если нужно указать несколько классов/типов, то они указываются через запятую.

• Параметром шаблона может быть не только тип, но и значение переменной.

Page 10: Объектно-Ориентированное Программирование на C++, Лекция 6

Шаблоны с переменным числом параметровCPP_Examples14_VariadicTemplatetemplate <class T> void print(const T& t) {

std::cout << t << std::endl;

}

template <class First, class... Rest> void

print(const First& first, const Rest&...

rest) {

print(rest...);

}

• В C++ есть возможность сделать шаблон с переменным числом параметров.

• В этом случае используется «…» для указания списка параметров.

• Работать с такими шаблонами можно по принципу рекурсии.

Page 11: Объектно-Ориентированное Программирование на C++, Лекция 6

Множественное наследование в шаблонахCPP_Examples14_DecoratorTemplate

template <typename... BaseClasses>

class Printer : public BaseClasses... {

public:

Printer(BaseClasses&&... base_classes) :

BaseClasses(base_classes)...

{

}

};

Page 12: Объектно-Ориентированное Программирование на C++, Лекция 6

Шаблоны в качестве параметров шаблоновCPP_Examples14_TemplateParameters

• Шаблон можно указать в качестве параметра шаблона!

• Все типы, которые используются при конструировании нового типа с помощью шаблона – должны быть его параметрами.

template <class T> class Payload

{

};

template <template <class> class PL, class T> class Printer

{

};

Printer<Payload, int> printer;

Page 13: Объектно-Ориентированное Программирование на C++, Лекция 6

Большая «скучная» книга про шаблоны (но самая лучшая)

Год выпуска: 2002Автор: Андрей АлександрескуЖанр: Программирование [C++]Издательство: Издательский дом "Вильямс" Москва - Санкт-Петербург - КиевISBN: 5-8459-0351-3(рус), 0-201-77581-6(англ.)Количество страниц: 326Описание: В книге изложена новая технология программирования, представляющая собой сплав обобщённого программирования шаблонов и объектно - ориентированного программирования на С++. Обобщённые компоненты, созданные автором, высоко подняли уровень абстракции, наделив язык С++ чертами языка спецификации проектирования, сохранив всю его мощь и выразительностьВ книге изложены способы реализации основных шаблонов проектирования. Разные компоненты воплощены в библиотеке Loki, которую можно загрузить с Web-страницы автора. Книга предназначена для опытных программистов на С++

Page 14: Объектно-Ориентированное Программирование на C++, Лекция 6

Перегрузка операций

Page 15: Объектно-Ориентированное Программирование на C++, Лекция 6

Прежде чем начать• Это механизм, при неумелом использовании

которого можно полностью запутать код.

• Непонятный код – причина сложных ошибок!

• Перегруженные операции помогают определить «свойства» созданного вами класса, но не алгоритма работы с классами!

Page 16: Объектно-Ориентированное Программирование на C++, Лекция 6

Перегрузка операцийМожно описать функции, для описания следующих операций:

+ - * / % ^ & | ~ !

= < > += -= *= /= %= ^= &=

|= << >> >>= <<= == != <= >= &&

|| ++ -- ->* , -> [] () new delete

Нельзя изменить приоритеты этих операций, равно как и синтаксические правила для выражений. Так, нельзя определить унарную операцию % , также как и бинарную операцию !.

Page 17: Объектно-Ориентированное Программирование на C++, Лекция 6

Синтаксисtype operator operator-symbol ( parameter-list )

Ключевое слово operator позволяет перегружать операции. Например:

• Перегрузка унарных операторов:◦ ret-type operator op ( arg )

◦ где ret-type и op соответствуют описанию для функций-членов операторов, а arg — аргумент типа класса, с которым необходимо выполнить операцию.

• Перегрузка бинарных операторов◦ ret-type operator op( arg1, arg2 )

◦ где ret-type и op — элементы, описанные для функций операторов членов, а arg1 и arg2 —аргументы. Хотя бы один из аргументов должен принадлежать типу класса.

Page 18: Объектно-Ориентированное Программирование на C++, Лекция 6

Префиксные и постфиксные операторы++ и --

Операторы инкремента и декремента относятся к особой категории, поскольку имеется два варианта каждого из них:

• преинкрементный и постинкрементный операторы;

• предекрементный и постдекрементный операторы.

При написании функций перегруженных операторов полезно реализовать отдельные версии для префиксной и постфиксной форм этих операторов. Для различения двух вариантов используется следующее правило: префиксная форма оператора объявляется точно так же, как и любой другой унарный оператор; в постфиксной форме принимается дополнительный аргумент типа int.

Пример:

friend Point& operator++( Point& ) // Prefix increment

friend Point& operator++( Point&, int ) // Postfix increment

friend Point& operator--( Point& ) // Prefix decrement

friend Point& operator--( Point&, int ) // Postfix decrement

Page 19: Объектно-Ориентированное Программирование на C++, Лекция 6

ПримерCPP_Examples16

class Rectangle

{

private:

int _width, _height;

public:

Rectangle(int width,int height) :

_width(width),_height(height) {}

friend Rectangle

operator+(Rectangle,Rectangle);

Rectangle operator++(){

_width ++;_height++;return *this;}

int operator[](int i){

switch (i)

{

case 0: return _width;

case 1: return _height;

default:

throw exception_ptr();

break;

}

}

};

Page 20: Объектно-Ориентированное Программирование на C++, Лекция 6

Переопределение оператора присваиванияCPP_Examples16_OperatorNew

Он должен быть нестатической функцией-членом. Никакой оператор operator= не может быть объявлен как функция, не являющаяся членом.

Он не наследуется производными классами.

Компилятор может создавать для типов классов функции operator= по умолчанию, если они не существуют. В этом случае оператор равно применяется к каждому члену класса.

Page 21: Объектно-Ориентированное Программирование на C++, Лекция 6

Делаем функторCPP_Examples16_OperatorFunctor

Синтаксис: primary-expression ( expression-list )

В этом контексте основное-выражение является первым операндом, а список-выражений(список аргументов, который может быть пустым) — вторым. Оператор вызова функции используется для операций, для которых необходимо определенное количество параметров. Такой подход действует потому, что список-выражений представляет собой не отдельный операнд, а список. Оператор вызова функции должен представлять собой нестатическую функцию-член.

Page 22: Объектно-Ориентированное Программирование на C++, Лекция 6

Перегрузка операторов new и deleteCPP_Examples16_OperatorConstructor

Операторы new и delete можно перегрузить. Для этого есть несколько причин:◦ Можно увеличить производительность за счёт кеширования: при удалении объекта не освобождать

память, а сохранять указатели на свободные блоки, используя их для вновь конструируемых объектов.

◦ Можно выделять память сразу под несколько объектов.

◦ Можно реализовать собственный "сборщик мусора" (garbage collector).

◦ Можно вести лог выделения/освобождения памяти.

Операторы new и delete имеют следующие сигнатуры:

void *operator new(size_t size);

void operator delete(void *p);

Оператор new принимает размер памяти, которую необходимо выделить, и возвращает указатель на выделенную память.

Оператор delete принимает указатель на память, которую нужно освободить.

Page 23: Объектно-Ориентированное Программирование на C++, Лекция 6

Статические классы и члены классовCPP_Examples17

Класс - это тип, а не некоторое данное, и для каждого объекта класса создается своя копия атрибутов, представляющих данные. Однако, наиболее удачная реализация некоторых типов требует, чтобы все объекты этого типа имели некоторые общие атрибуты.

class task {

static void shedule(int); // метод класса

static task* chain; //атрибут класса

};

if (task::chain == 0) // какие-то операторы

Page 24: Объектно-Ориентированное Программирование на C++, Лекция 6

Singleton◦ Описание задачи

В программе существуют глобальные объекты с одним экземпляром на всю программу.

◦ Описание решенияКласс объекта хранит ссылку на сам объект и может инициировать создание объекта как при первом обращении так и при старте программы.

◦ Когда применятьВсегда когда нужно хранить глобальные свойства системы или иметь доступ к глобальному ресурсу (если он может существовать только в одном экземпляре)

◦ ПримерНапример, при отправке сообщений в очередь мы хотим убедится что у нас не будет конфликтов из-за многопоточности. Поэтому мы создаем один объект по работе с данной очередью и вставляем в нем мониторы.

24

Page 25: Объектно-Ориентированное Программирование на C++, Лекция 6

SingletonПреимущества◦ контролируемый доступ к единственному экземпляру.

◦ уменьшение числа имен, используемых в системе.

◦ допускает уточнение операций и представления.

◦ допускает переменное число экземпляров.

◦ большая гибкость, чем у операций класса.

Реализация◦ гарантирование единственного экземпляра.

◦ порождение подклассов Singleton (при необходимости).

25

Page 26: Объектно-Ориентированное Программирование на C++, Лекция 6

mcSingletonДолжен остаться только один!

26

Page 27: Объектно-Ориентированное Программирование на C++, Лекция 6

SingletonCPP_Examples18

class McLeod

{

private:

static McLeod* _instance;

McLeod(){

cout << "I am alive!\n";}

public:

static McLeod * GetInstance(){

if(_instance==NULL) _instance = new McLeod();

return _instance;}

void Print() { cout << "I am only one!\n";}

static void Die()

{

if(_instance!=NULL)

{

delete _instance;

_instance = NULL;

}

}

};

27