Шаблоны и наследование. Шаблоны и конфигурация компиляторов. Достоинства и недостатки шаблонов

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

template<список_аргументов_шаблона>

class имя_класса

{

тело_класса

};

class идентификатор

тип_идентификатора

Тело классу аналогично обычному определению класса и отличается от последнего тем, что может содержать типы и идентификаторы из списка аргументов шаблона.

Шаблон класса стек

template<class Type>

class Stack

{

Type *s;

int maxlen;

enum EMPTY=-1;

int top;

public:

Stack(int size=1000):maxlen(size)

{

s=new Type[size];

top=EMPTY;

}

~Stack()

{

delete[]s;

}

void Reset

{

top=EMPTY;

}

void Push(Type c) {...}

Type Pop(){return s.top;}

Type Topof(){return s.top;}

Type Empty();

int Full();

}

template <class T>

class Stack

{ enum {EMPTY=-1};

T *s;

int man_len;

int top;

public:

Stack(int);

~Stack();

void Reset();

void Push();

T Pop();

T Topoff();

int Empty();

int Full();

};

Функции члены, которые объявлены внутри класса, являются встраиваемые. При внешнем объявлении должно использоваться полное объявление метода со всеми угловыми скобками.

template <class T>

T Stack<T>::Topoff()

{

return s[top];

}

Такое сложное на первый взгляд описание надо для того, чтобы сообщить компилятору, что Т является параметром шаблона.

Stack<char>stk_ch;//компилятор по первой записи генерирует стек записей

Stack<char*>stk_ch(200);

Stack<complex>stk_cmpx(300);

//пример реверсирования строк

void Reverse(char *str[], int n)

{

Stack<char*>stk(n);

for(int i=0;i<n;i++)

{

stk.Push(str);

}

for(i=0;i<n;i++)

str[i]=stk.Pop();

}

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

template <class T, int size>

Stack<char>stk_ch;

Stack<char*>stk_ch(200);

Stack<complex>stk_cmpx(300);

Stack<char, 100> stk_ch;

Stack<char, 10> stk_ch(10);

Stack<char, 20> stk_ch(20);

Для нетиповых параметров шаблона допускается использование значений по умолчания, подобно значениям по умолчанию для классов.

template <class T, int size=100>

Ключевое слово typedef с шаблонами

Для шаблонного класса может быть применено ключевое слово typedef, которое может существенно упростить его использование.

typedef Stack<char> cstack;

catack stk_ch10(10);

Явная реализация некоторых методов шаблона для специфических типов

Можно специализировать шаблон класса, предусмотрев для специфических типов реальную реализацию некоторых типов. Для стека можно было реализовать метод Push для реализации начала. Для этого надо:

  1. Вынести определение функции за пределы класса
  2. В том случае, когда обобщенная функция описывается как inline, ее определение должно быть за определением специализированной функции. В противном случае, компилятор считает, что уже имеет определение специализированной функции.

template<class T>

class Stack

{

...

void Push(T c);

...

};

inline void Stack<char *>::Push(char *c)

{

s[++top]=new char [strlen(c)++]

strcpy(s[top],c);

}

template<class P>

inline void Stack<T>::Push(T c)

{

s[++top]=c;

}

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

template<class P> class Matrix

{

...

friend void Number();//Дружественная к любой реализации

friend Vect<T>product(Vector <T>);//реализованная дружественная функция

...

};

Статические члены класса не универсальны, а специфичны для каждой реализации шаблона.

По таким определениям будут определены две разные статические переменные