Шаблоны функций

Шаблоны функций и классов

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

Реализация таких параметризированных (обобщенных) классов и функций требует чтобы в языке программирования были средства для их реализаций. В языке С++ таким средством являются шаблоны (templates).

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

void swap(int& x, int& y) { int temp; temp=x; x=y; y=temp; } template<class TYPE> void swap(TYPE& x, TYPE& y) { TYPE temp; temp=x; x=y; y=temp; }

Таким образом, для создания шаблона мы заменили тип int на лексему TYPE с помощью ключевого слова template в скобках <>. Компилятор же выполнит замену наоборот, он заменит лексему TYPE на любой тип, который ему указать:

double x=1, y=5;
swap<double> (x,y); // в данном случае тип double

Генерация функции по шаблону и ее аргументу называется инстанцирование. Возможно выведение типа аргумента шаблона по типам его аргументов, но я рекомендую явно указывать параметр в скобках <>. Часто возникает необходимость использовать несколько параметров у одной функции шаблона. Это осуществляется следующим образом:

template<class PAR1, class PAR2>
bool transform(PAR1 x, PAR2& y)
{
if(sizeof(y) < sizeof(x))
{
return false;
}
y=(PAR2)x;
return true;
}
//или так:
template<class PAR, int n>
PAR1 factorial()
{
PAR sum=1;
i=1;
while(i<=n)
{
sum*=i;
i++;
}
return sum;
}

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

Шаблоны позволяют реализуют в языке С++ такое отношение между классами, как инстанцирование. При создании шаблона класса тип одного или нескольких его переменных членов задаются в качестве параметра. При использовании этого шаблона необходимо будет указать, какой тип использовать в качестве параметра. Это и называется инстанцированием. Например, обобщенный класс Matrix. Многие классы, которые используются для хранения и управления гомогенными структурами данных, раелизуют в виде шаболнов. И действительно, независимо от типов хранимых в нем элементов, класс Matrix должен выполнять одни и те же функции (разместить матрицу в памяти, организовать доступ к любому элементу, обеспечить выполнение операций сложения, умножения матриц и др.)

template <class PAR>
class Matrix
{
protected:
//Члены
int m_cols; //количество колонок
int m_rows; //количество строк
PAR* m_p_matrix; //указатель на массив матрицы
public:
//Конструктор (выделяет память для заданного размера)
Matrix(int row, int col);
//Конструктор копирования
Matrix(const Matrix<PAR>& one);
//Деструктор
~Matrix();

//Создание
void Create(int row, int col);

//Доступ к элементам матрицы
PAR GetAt(int row, int col) const;
void SetAt(int row, int col, PAR one);
PAR& ElementAt(int row, int col);
PAR operator() (int row, int col) const;
PAR& operator() (int row, int col);
};

//Конструктор по умолчанию (выделяет память для заданного размера)
template<class PAR>
Matrix<PAR>::Matrix(int row, int col)
{
Create(row,col);
}

// Конструктор копирования
template<class PAR>
Matrix<PAR>::Matrix(const Matrix<PAR>& one)
{
Create(one.m_rows,one.m_cols);
memcpy(m_p_matrix, one.m_p_matrix, m_cols*m_rows*sizeof(PAR));
}

// Создание матрицы
template<class PAR>
void Matrix<PAR>::Create(int row, int col)
{
if ((col*row)>0)
{
m_cols=col;
m_rows=row;
m_p_matrix=new PAR [m_cols*m_rows];
}
}

// Деструктор
template<class PAR>
Matrix<PAR>::~Matrix()
{
delete [] m_p_matrix;
}

//Доступ к элементам матрицы
//Возвращает значение элемента матрицы с индексами col и row
template<class PAR>
PAR Matrix<PAR>::GetAt(int row, int col) const
{
return (m_p_matrix[row*m_cols+col]);
}

//Возвращает значение элемента матрицы с индексами col и row
template<class PAR>
PAR& Matrix<PAR>::ElementAt(int row, int col)
{
return (m_p_matrix[row*m_cols+col]);
}

//Устанавливает значение элемента матрицы
template<class PAR>
void Matrix<PAR>::SetAt (int row, int col, PAR one)
{
m_p_matrix[row*m_cols+col]=one;
}

//Оператор доступа к элементам
template<class PAR>
PAR Matrix<PAR>::operator() (int row, int col) const
{
return (GetAt(row,col));
}

// Оператор доступа к элемнентам
template<class PAR>
PAR& Matrix<PAR>::operator() (int row, int col)
{
return (ElementAt(row,col));
}

Процесс генерации объявления класса по шаблону и аргументу называется инстанцированием шаблона.

Matrix<int> A(5,5), B(3,3);
Matrix<double> X(150,150);


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: