Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по Программированию.doc
Скачиваний:
49
Добавлен:
11.02.2015
Размер:
1.22 Mб
Скачать

Шаблоны классов

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

Предположим, что нам нужно определить класс, поддерживающий механизм очереди. Очередь – это структура данных для хранения коллекции объектов; они помещаются в конец очереди, а извлекаются из ее начала. Поведение очереди описывают аббревиатурой FIFO —«первым пришел, первым ушел».

Тогда объявление класса Queueбудет выглядеть примерно так:

class Queue {

public:

Queue();

~Queue();

Type& remove();

void add( const Type & );

bool is_empty();

bool is_full();

private:

// ...

};

Вопрос в том, какой тип использовать вместо Type? Предположим, что мы решили реализовать классQueue, заменивTypeнаint. ТогдаQueueможет управлять коллекциями объектов типаint. Если бы понадобилось поместить в очередь объект другого типа, то его пришлось бы преобразовать в типint, если же это невозможно, компилятор выдаст сообщение об ошибке.

Конечно, эту проблему можно решить, создав копию класса Queueдля работы с типомdouble, затем для работы с комплексными числами, затем со строками и т.д. А поскольку имена классов перегружать нельзя, каждой реализации придется дать уникальное имя:IntQueue,DoubleQueue,ComplexQueue,StringQueue. При необходимости работать с другим классом придется снова копировать, модифицировать и переименовывать.

Механизм шаблонов C++ позволяет автоматически генерировать такие типы. Шаблон класса можно использовать при создании Queueдля очереди объектов любого типа. Определение шаблона этого класса могло бы выглядеть следующим образом:

template <class Type>

class Queue {

public:

Queue();

~Queue();

Type& remove();

void add( const Type & );

bool is_empty();

bool is_full();

private:

// ...

};

Чтобы создать классы Queue, способные хранить целые числа, комплексные числа и строки, программисту достаточно написать:

Queue<int> qi;

Queue<complex> qc;

Queue<string> qs;

Пример: Реализация шаблона классаCStack— стек на основе динамического массива.

// Файл CStack.h

#ifndef _CStack_H

#define _CStack_H

#include <iostream.h>

#include <stdlib.h>

template <class Type>

class CStack {

private:

Type *data; //Массив для хранения стека

int top; //Индекс вершины стека

int size; //Макс. размер стека

public:

CStack(int); //Конструктор – передается максимальное количество элементов

~CStack() {free(data);}

void push(Type); //Добавление эл-та

int pop(Type &); //Выталкивание эл-та. Возвращает 0, если стек пуст

int isempty() {return !top;}

void print(); //Вывод содержимого стека

};

template <class Type>

CStack<Type>::CStack(int sz)

{

data=(Type*) calloc(sz, sizeof(Type));

top=0;

size=sz;

}

template <class Type>

void CStack<Type>::push(Type Item)

{

if (top==size)

{ //Если массив заполнен - расширить

size+=8;

data=(Type*)realloc(data, size*sizeof(Type));

}

data[top++]=Item;

}

template <class Type>

int CStack<Type>::pop(Type &Item)

{

if (!isempty())

{

Item=data[--top];

return 1;

}

else return 0;

}

template <class Type>

void CStack<Type>::print()

{

for (int i=top-1; i>=0; i--)

cout << data[i] << ' ' ;

cout << endl ;

}

#endif

//Тестирующая программа

#include <stdio.h>

#include <math.h>

#include "CStack.h"

int main(int argc, char* argv[])

{

printf("Int\n");

CStack <int> ti(2);

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

ti.push(i);

ti.print();

int k;

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

if (ti.pop(k)) printf("%d\n",k);

else printf("Empty\n");

printf("Double\n");

CStack <double> td(2);

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

td.push(sqrt((double)i));

td.print();

double f;

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

if (td.pop(f)) printf("%lf\n",f);

else printf("Empty\n");

getchar();

return 0;

}

Результаты работы программы:

Int

3 2 1 0

3

2

1

0

Empty

Empty

Empty

Double

3.60555 3.4641 3.31662 3.16228

3.605551

3.464102

3.316625

3.162278

Empty

Empty

Empty