Шаблон типа для класса задает способ построения отдельных классов, подобно тому, как описание класса задает способ построения его отдельных объектов. Можно определить стек, содержащий элементы произвольного типа:
template<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; } };
Для простоты не учитывался контроль динамических ошибок. Не считая этого, пример полный и вполне правдоподобный.
Префикс template<class T> указывает, что описывается шаблон типа с параметром T, обозначающим тип, и что это обозначение будет использоваться в последующем описании. После того, как идентификатор T указан в префиксе, его можно использовать как любое другое имя типа. Область видимости T продолжается до конца описания, начавшегося префиксом template<class T>. Отметим, что в префиксе T объявляется типом, и оно не обязано быть именем класса. Так, ниже в описании объекта sc тип T оказывается просто char.
Имя шаблонного класса, за которым следует тип, заключенный в угловые скобки <>, является именем класса (определяемым шаблоном типа), и его можно использовать как все имена класса. Например, ниже определяется объект sc класса stack<char>:
stack<char> sc(100); // стек символов
Если не считать особую форму записи имени, класс stack<char> полностью эквивалентен классу определенному так:
class stack_char { char* v; char* p; int sz; public: stack_char(int s) { v = p = new char[sz=s]; } ~stack_char() { delete[] v; }
void push(char a) { *p++ = a; } char pop() { return *--p; }
int size() const { return p-v; } };
Можно подумать, что шаблон типа - это хитрое макроопределение, подчиняющееся правилам именования, типов и областей видимости, принятым в С++. Это, конечно, упрощение, но это такое упрощение, которое помогает избежать больших недоразумений. В частности, применение шаблона типа не предполагает каких-либо средств динамической поддержки помимо тех, которые используются для обычных "ручных" классов. Не следует так же думать, что оно приводит к сокращению программы.
Обычно имеет смысл вначале отладить конкретный класс, такой, например, как stack_char, прежде, чем строить на его основе шаблон типа stack<T>. С другой стороны, для понимания шаблона типа полезно представить себе его действие на конкретном типе, например int или shape*, прежде, чем пытаться представить его во всей общности.
Имея определение шаблонного класса stack, можно следующим образом определять и использовать различные стеки: