Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PP_laba13.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
71 Кб
Скачать
☆

5.1.1 Пример класса-шаблона

Листинг 11.1. Простой массив – шаблон

#include <stdexcept>

template <class T, std::size_t N>

// параметры шаблона

class Array

{

public:

// типы

typedef T value_type;

typedef T &reference;

typedef const T &const_reference;

typedef std::size_t size_type;

static const size_type static_size = N;

// размер массива

Array(const T &t = T());

// конструктор

size_type size() const

// получение размера

{ return static_size; }

reference operator[](const size_type &i)

// доступ к элементам

{ rangecheck(i); return elem[i]; }

const_reference operator[](const size_type &i) const

{ rangecheck(i); return elem[i]; };

private:

void rangecheck (const size_type &i) const // проверка индекса

{

if (i >= size()) { throw std::range_error("Array - range!"); }

}

T elem[N]; // поле-массив

};

template <typename Т, std::size_t N>

// реализация конструктора

Array <T,N>::Array(const T &t)

{ for (int i = 0; i<N; i++) elem[i] = t; }

Функциональность класса – минимальная. В начале класса-шаблона определе­но несколько типов-синонимов. Проверка индекса в операциях индексирования [] выполняется приватной функцией rangecheck(), которая генерирует стандартное исключение при «вылете» за границу массива.

Конструктор инициализации является и конструктором по умолчанию. Конст­руктор класса-шаблона задан внешним образом: определение метода должно на­чинаться со слова template вместе с параметрами шаблона:

template <typename Т, std::size_t N>

Тип класса-шаблона Array <T, N>:: задается в качестве префикса. В теле метода для всех имен класса префикс может отсутствовать. Для методов, определенных внутри шаблона, префиксы не указываются.

Параметру присвоено значение по умолчанию

const Т &t = Т()

При инстанцировании шаблона (подстановка конкретного типа) эта конструк­ция означает инициализацию нулем для элементарных встроенных типов; а для классов влечет вызов конструктора по умолчанию (то есть класс, используемый в качестве подставляемого аргумента шаблона, должен иметь конструктор по умолчанию).

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

elem[i] = Т();

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

В классе-шаблоне разрешено использовать инициализацию нулем и в списке ини­циализации конструктора. Если отказаться от присвоения значения по умолча­нию и использовать явное обнуление, конструктор класса-шаблона примет вид:

template <typename Т, std::size_t N>

// реализация конструктора

Array <T, N>::Array():elem() { }

Массив будет проинициализирован нулем, если вместо Т подставить встроенный тип. Для классов тогда будет вызываться конструктор без аргументов.

Использовать такой шаблон  просто.

Array <int, 10> w;// инициализируем нулем

Array <int, 10> t(0);// инициализируем нулем

Array <int, 10> r(t);// конструктор копирования

Array <double, 50> р(2);// все элементы = 2

for (int i = 0; i < p.size(); i++)

cout << p[i] << ' ';// доступ справа

for (int i = 0; i < p.size(); i++)

p[i] = i;// доступ слева

В качестве типа-аргумента могут подставляться любые возможные типы, опре­деление которых видимо в точке объявления переменной-массива.

Array <void*, 100> рр; // массив указателей

Array<Pair <int, int>, 100> mр; // массив объектов-пар

Array<Pair<long,int>*,10> *mpp; // указатель на массив

// указателей на пары

Array<date, 10> dd; // массив дат

Класс date должен иметь конструктор без аргументов, вызываемый в конструк­торе массива.

Действительно также и присваивание:

w = г; // присваиваем - типы одинаковы

Копирование и присваивание работают только для массивов с одинаковым типом элементов и размером массива. Изменяя тип элементов и (или) размер, получа­ем массивы разных типов. При попытках использовать оператор присваивания или конструктор копирования с такими разнотипными массивами компилятор выдает сообщение о невозможности преобразования типов. Например, нельзя написать присвоение

р = t;

Слева массив с типом элементов double, а справа  int. Преобразование типов по умолчанию не выполняется.

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

Array<double, 10> F(const Array <int, 10> &t);

Эта функция получает ссылку на массив из 10 элементов типа int, а возвращает массив из 10 элементов типа double. Нужно также помнить, что преобразование типов по умолчанию не работает.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]