Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции C++.doc
Скачиваний:
7
Добавлен:
01.05.2025
Размер:
1.44 Mб
Скачать

9.2 Функции с двумя типами-шаблонами

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

#include <iostream.h>

template <class type1, class type2> void F(type1 &x, type2 &y)

{

cout << x << ' ' << у << endl;

}

int main()

{

F(10, "hi"); F(0.23, ‘q’);

return 0;

}

В этом примере типы-шаблоны type1 и type2 заменяются компилятором на типы int, char*, double и char соответственно, причем компилятор сгенерирует два различных экземпляра функции F(). Следует иметь в виду, что когда создается функция-шаблон, то по существу этим компилятору разрешается создавать столько различных версий этой функции, сколько необходи­мо, чтобы обрабатывать те типы данных, которые передаются этой функции при ее вызове.

9.3 Ограничения на функции-шаблоны

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

Другим ограничением на функции-шаблоны является то, что виртуальная функция не может быть функцией-шаблоном.

9.4 Классы-шаблоны

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

Классы-шаблоны полезны тогда, когда класс содержит логику, допускающую значительные обобщения. Например, алгоритм для обработки очереди целых чисел также будет работать с очередью символов. Аналогично механизм, поддерживающий связанный список почтовых адре­сов, также может поддерживать связанный список сведений об автомобилях. Используя классы-шаблоны, можно создавать классы, поддерживающие очереди, связанные списки, массивы и т. д. для про­извольных типов данных. Компилятор автоматически создаст корректный код, основываясь на типе данных, указанном перед компиляцией. Общая форма объявления класса-шаблона показа­на ниже:

template <class тип1, class тип2, ...> class имя_класса

{

// тело класса

};

Здесь тип1, тип2, и т.д. являются параметрами-типами, которые будут указаны при создании экземпляра класса.

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

имя_класса<тип> объект;

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

функции-члены класса-шаблона являются сами по себе автоматически шаблонами. Нет необхо­димости особым образом указывать на то, что они являются шаблонами, с использованием ключе­вого слова template.

В следующей программе создается класс-шаблон stack, реализующий стандартный стек «послед­ним вошел - первым вышел». Он может использоваться для реализации стека с произвольным типом данных. В представленном здесь примере создаются стеки символов, целых чисел и чисел с плавающей точкой.

#include <iostream.h>

const int SIZE = 100;

template<class X> class stack

{

X st[SIZE];

int top;

public:

stack() { tos = 0; cout << "Stack initialized\n"; }

~stack() { cout << "Stack Destroyed\n; }

void push(X i)

{

if(top == SIZE) { cout << "Stack is full.\n"; return; }

st[top++] = i;

}

X pop()

{

if(top == 0) { cout << "Stack underflow.\n"; return 0; }

return st[--top];

}

};

int main()

{

stack<int> a; // создание целочисленного стека

stack<double> b; // создание вещественного стека

stack<char> с; //создание символьного стека

a.push(1); a.push(2); b.push(99.3); b.push(-12.23);

cout << a.pop() << " " << a.pop() << " ";

cout << b.pop() << " " << b.pop() << "\n";

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

с.push((char)('A' + i));

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

cout << c.pop();

cout << "\n";

return 0;

}

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

stack<int> a; // создание целочисленного стека

stack<double> b; // создание вещественного стека

stack<char> с; // создание символьного стека

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

stack<char*> char_ptr_stack;

Также можно создать стек, содержащий определенный тип данных. Например, можно хранить адреса, используя структуру:

struct addr

{

char name[40];

char street[40];

char city[30];

char state[3];

char zip[12]; }

Далее можно использовать класс stack для создания стека, в котором хранятся объекты типа addr:

stack<addr> obj;