PDA

Просмотр полной версии : [Урок] [Цикл уроков программиста] 16.Шаблоны (templates): шаблонные классы и функции в C++



Tracker1
30.07.2013, 20:38
Последний урок в вводном курсе С++

Шаблоны (templates) - очень мощное средство. Шаблонные функции и классы позволяют очень сильно упростить программисту жизнь и сберечь огромное количество времени, сил и нервов. Если вам покажется, что шаблоны не сильно-то и значимая тема для изучения, знайте - вы заблуждаетесь.
Шаблонные функции

Простой пример шаблонной функции:


Type square (Type a)
{
Type b;
b = a*a;
return b;
}

int x = 5;
int i;

i = square(5);

float y = 0.5;
float f;

f = square(y);


Если бы мы создавали функции по старинке, то тогда бы пришлось писать две разные функции: для типа int и для типа float. А если бы понадобилась такая же функция, использующая другие типы, пришлось бы заново писать и её. Используя шаблоны, можно ограничиться только одним экземпляром функции, оставив всю грязную работу компилятору.

Вместо использования какого-то определённого типа, в функции используется параметрический тип (или по другому - аргумент шаблона). Здесь я обозвал параметрический тип идентификатором Type. В функции этот идентификатор встречается три раза: возвращаемое значение, аргумент функции и определение переменной b. То есть Type используется как любой обычный тип.

Но чтобы код заработал, перед функцией нужно добавить следующую строку (я показал несколько вариантов синтаксиса, все они рабочие):


template <class Type> Type square (Type a)

template <class Type>
Type square (Type a)

template< class Type >
Type square (Type a)

template < class Type > Type square (Type a)


Итак, перед функцией должно стоять ключевое слово template (шаблон), а в угловых скобках нужно указать имя параметрического типа с ключевым словом class. Вместо ключевого слова class можно использовать type - в общем-то никакой разницы.

Идентификатор параметрического типа тоже может быть любым. Мы часто будем пользоваться вот такими: TypeA, TypeB, Datatype, T.

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

В шаблонах можно использовать несколько параметрических типов, и конечно же можно смешивать параметрические типы со стандартными (только нужно позаботиться о правильном приведении типов). Приведу пример в котором используется два параметрических типа TypeA, TypeB и базовый тип int:


template <class TypeA, class TypeB>
TypeB example_function (TypeA a, TypeB b)
{
int x = 5;
b = a + x;
return b;
}


Но шаблонные функции - не самое интересное, что мы сегодня рассмотрим.
Шаблонные классы

В общем-то шаблонные классы создаются почти так же как и шаблонные функции - перед именем класса записывается ключевое слово template. Шаблонные классы рассмотрим на примере стека:


template <class Type>
class stack
{
private:
int top;
Type s[10];

public:
stack (): top(0)
{}

void push(Type var)
{
top++;
s[top] = var;
}

Type pop();
};

template <class Type>
Type stack<Type>::pop()
{
Type var = s[top];
top--;
return var;
}


Здесь мы определили стек из десяти элементов. Эти элементы могут быть какого угодно типа, об этом чуть-чуть ниже.

Единственное на что хочу обратить ваше внимание: определение функций push и pop. Функция push определена внутри класса, а функция pop - снаружи. Для всех функции объявлённых за пределами класса, нужно обязательно указывать ключевое слово template. Выражение перед именем функции совпадает с тем, которое указывается перед именем класса.

Теперь посмотрим как работать с шаблонными классами:


stack<int> s1;
stack<float> s2;

s1.push(3);
s1.push(2);
s1.pop();

s2.push(0.5);


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

У шаблонных классов есть одна потрясающая особенность - кроме стандартных типов, они могут работать и с пользовательскими. Рассмотрим небольшой пример. Для этого определим простой класс warrior:


class warrior
{
public:
int health;
warrior () : health(0) {}
};

stack<warrior> s;

warrior w1;
warrior w2;
warrior w3;

s.push(w1);
s.push(w3);

s.pop();
s.push(w2);


Смотрите, теперь в стеках можно размещать переменные типа warrior!!! Возможно вы не поверите мне, но это очень круто!

По шаблонам пока всё. Позже разберём более сложные случаи использования шаблонных классов.
Упражнения

Напишите шаблонный класс для очереди. Код обычной очереди вы можете взять в упражнении 1

#MAVRIN
30.07.2013, 22:30
фейк

Will_Winston
30.07.2013, 22:32
Естественно :)

Tracker1
31.07.2013, 11:42
фейк


Естественно :)

Схуяли вы это так решили?

Osetin
31.07.2013, 11:44
Не фейк,настоящий))

Will_Winston
31.07.2013, 12:21
Да фейк это...

Tracker1
31.07.2013, 12:43
Да фейк это...

А доказать можешь? Или кроме голословных заявлений ты ни на что более не способен?

Will_Winston
31.07.2013, 12:53
Что мне доказвать? Думаешь что пишешь? Это ты должен доказать....

Tracker1
31.07.2013, 12:55
Что мне доказвать? Думаешь что пишешь? Это ты должен доказать....

Может это ты подумаешь?
Презумпция невиновности. Ты не можешь доказать что я фейк - значит я настоящий.

Drive666
31.07.2013, 12:55
Что мне доказвать? Думаешь что пишешь? Это ты должен доказать....
Ты и должен доказать что он фейк,раз уж обвиняешь его!!

Will_Winston
31.07.2013, 12:58
Может это ты подумаешь?
Презумпция невиновности. Ты не можешь доказать что я фейк - значит я настоящий.

Да мне уже как-то *** настоящий ты не настоящий,всё прекрати тогда этот спор.

Tracker1
31.07.2013, 13:00
Да мне уже как-то *** настоящий ты не настоящий,всё прекрати тогда этот спор.

Аргументов нет, потому и слился?
Пустослов ты вот и всё. Хватит срать в моей теме.