Skip to content

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

Pandas edited this page Jun 16, 2017 · 2 revisions

Проверка шаблона на корректность происходит только при его использовании. В зависимости от передаваемых параметров шаблон может работать корректно или некорректно. Однако шаблоны достаточно полезны – если есть несколько функций, совершающих одни и те же действия над разными объектами, можно написать шаблон функции. Шаблон задает функцию для работы с разными типами данных. При создании есть параметр типа.

//Пример – определение размера файла.
template <typename/*или class*/ T> unsigned length(FILE *fv)
{
	return filelength(fileno(fv)) / sizeof(T); //возвращает размер в байтах, делённый на количество байт в типе
}

FILE *f;
...
unsigned Count = length<double>(f);

Если мы явно передаём в список параметров значения с параметрами шаблона, то указывать специализацию (..< double >) не нужно. Функция может иметь параметры по умолчанию того же типа что и шаблон – тогда специализация нужна. Кроме того, специализацию можно указывать КОНСТАНТНОЙ переменной – написать const double P и писать length< P >.

template<typename T> T inc(T &i, T di)
{
	return i += di;
}

int i=0;
inc(i,5);
double d=3.2;
inc(d,1.1);

Более того – можно в ШАБЛОНЕ задавать параметры по умолчанию, <typename T=int>

При работе с классами процедура аналогична. В данном случае шаблон НЕ ЕСТЬ класс – по шаблону мы будем создавать какой-либо класс.

template <typename T1, typename T2>
class A //<int, double> - конкретный класс, <int, T2> - шаблон с частичной специализацией
{
	/*...*/
};

///Примеры частичных специализаций:
template <typename T>
class A<T,T>
{};

template <typename T1, typename T2>
class A<T1*,T2*> //если при создании класса будем специализировать указатель адресами, то будет использоваться этот шаблон, а не верхний
{};

В случае функций – мы получали перегруженные функции. Здесь мы получаем совершенно разные классы. Параметры-значения можно инициализировать константами (целого типа) или указателями на объекты с внешним связыванием (определенные вне данного файла).

//Использование специализации при определении: 
template <typename T, size_t Size> //сайз – константа //пример того чего не надо делать
class Vector
{
	T v[Size];
	/*...*/
};
//при определении обязательно специализировать значение параметра
//частичной специализации быть не может - должен создаться объект конкретного класса
Vector<double,10> V1;
Vector<double,20> V2;

Два объекта разных классов. Что не есть торт. Если использование шаблона идёт локально то всё нормально, но если его передавать куда-то – то методы других классов должны быть опять-таки шаблонными.
Таким образом, пока мы не создадим чего-нибудь, мы не сможем проверить. Ошибки в шаблонах могут сидеть чрезвычайно долго. Шаблоны хороши только при локальном использовании.

Допускается выделять базовый класс вне шаблона; шаблон же будет производной от него. На уровне же шаблона необходимо будет реализовывать только операции для передачи данного, транзитные операции (данное принимается, куда-то передаётся, а там где начинаем работать – работаем уже конкретное приведение типа со специализацией). Таким образом решается проблема классов-посредников.

class A {};
template <typename T> //использование в шаблоне базового класса
class B: public A
{
public:
	int f();
};
template<typename T>
int B<T>::f()
{
}

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

Clone this wiki locally