Объективное программирование

Методическое пособие - Компьютеры, программирование

Другие методички по предмету Компьютеры, программирование

но часто классы создаются для объединения

множества элементов данных, которые внутри объекта могут

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

При этом объект класса содержит ссылки

 

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

класса (шаблон), в котором в виде параметра задан тип

(класс) входящих в него внутренних элементов данных. Тогда

при создании объекта необходимо дополнительно указывать и

конкретный тип внутренних элементов в качестве параметра.

Создание объекта сопровождается также и созданием

соответствующего конкретного класса для заданного конктретного типа.

Принятый в Си++ способ определения множества классов

с параметризованным внутренним типом данных (иначе, макроопределение) называется шаблоном (template). Синтаксис

шаблона рассмотрим на примере шаблона класса векторов,

содержащих динамический массив ссылок на переменные заданного типа.

 

--- параметр шаблона - класс "T", внутренний

тип данных

--- имя группы шаблонных классов

template class vector

{

inttsize;// Общее количество элеметов

intcsize;// Текущее количество элементов

T**obj;// Массив ссылок на параметризован// ные объекты типа "T"

public:

T *operator[](int);

// оператор [int] возвращает ссылку

// на параметризованный объект

// класса "T"

voidinsert(T*);// функция включения объекта типа "T"

intextract(T*);//

};

Данный шаблон может использоваться для порождения

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

шаблона "vector" и имени типа данных (класса), который подставляется вместо параметра "Т":

vectora;

vectorb;

extern classtime;

vectorc;

 

Заметим, что транслятором при определении каждого

вектора с новым типом объектов генерируется описание нового

класса по заданному шаблону (естественно, неявно в процессе

трансляции):

 

class vector

{

inttsize;

intcsize;

int**obj;

public:

int *operator[](int);

voidinsert(int*);

intindex(int*);

};

 

Далее следует очевидное утверждение, что элементыфункции шаблона также должны быть параметризованы, то есть

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

очередь также являются шаблонными функциями с тем же самым

параметром. То же самое касается переопределяемых операторов:

 

--- параметр шаблона - класс "T", внутренний

тип данных

--- имя элемента-функции или

оператора - параметризовано

template ::operator[](int n)

{

if (n >=tsize) return(NULL);

return (obj[n]);

}

 

template ::index(T *pobj)

{

intn;

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

if (pobj == obj[n]) return(n);

return(-1);

}

 

Заметим, что транслятором при определении каждого

вектора с новым типом объектов генерируется набор элементовфункций по заданным шаблонам (естественно, неявно в процессе

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

определение шаблона самого класса.

 

int* vector::operator[](int n)

{

if (n >=tsize) return(NULL);

return (obj[n]);

}

 

int vector::index(int *pobj)

{

intn;

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

if (pobj == obj[n]) return(n);

return(-1);

}

Шаблоны могут иметь также и параметры-константы,

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

может использоваться для размещения не только ссылок на

параметризованные объекты, но и сами объекты. В качестве

примера рассмотрим шаблон для построения циклической очереди ограниченного размера для параметризованных объектов.

template class FIFO

{

intfst,lst;// Указатели на начало-конец

// очереди

Tqueue[size];// Массив объектов класса "T"

// размерности "size"

public:

Tfrom();// Функции включения-исключения

voidinto(T);//

FIFO();// Конструктор

};

 

template ::FIFO()

{

fst = lst = 0;

}

 

template ::from()

{

T work;

if (fst !=lst)

{

work = area[lst++];

lst = lst % size;

}

return(work);

}

 

template ::into(T obj)

{

area[fst++] = obj;

fst = fst % size;

}

Пример использования:

FIFOa;

FIFOb;

structx {};

FIFOc;

Пример сгенерированного компилятором класса для объекта "a".

 

class FIFO

{

intfst,lst;

doublequeue[100];

public:

doublefrom();

voidinto(double);

FIFO();

};

 

FIFO::FIFO()

{

fst = lst = 0;

}

 

double FIFO::from()

{

double work;

if (fst !=lst)

{

work = area[lst++];

lst = lst % 100;

}

return(work);

}

void FIFO::into(double obj)

{

area[fst++] = obj;

fst = fst % 100;

}