C++. Понятие шаблона класса. Ключевое слово template. Преимущества использования шаблонов. Примеры объявления и использования шаблонов классов. Аргументы в шаблонах




Понятие шаблона класса. Ключевое слово template. Преимущества использования шаблонов. Примеры объявления и использования шаблонов классов. Аргументы в шаблонах


Содержание


Поиск на других ресурсах:

1. Что называется шаблоном класса? Что такое шаблон класса?

Часто, при разработке классов для разных типов данных, программисту приходится писать программный код для каждого типа в отдельности. Методы и операции над данными разных типов могут содержать один и тот же повторяемый код. Во избежание повторяемости написания кода для разных типов данных, в языке C++ используются так называемые шаблоны (templates).

Шаблон класса позволяет оперировать данными разных типов в общем. То есть, нет привязки к некоторому конкретному типу данных (int, float, …). Вся работа выполняется над некоторым обобщенным типом данных, например типом с именем T.

Фактически, объявление шаблона класса есть только описанием. Создание реального класса с заданным типом данных осуществляется компилятором в момент компиляции, когда объявляется объект класса.

2. Какая общая форма объявления шаблона класса и объекта шаблонного класса, которые не содержат аргументов? Ключевое слово template

В простейшем случае общая форма объявления шаблона класса без аргументов имеет следующий вид:

template <class T> class ClassName
{
    // тело класса
    // ...
}

где

  • T – обобщенное имя типа, который используется методами класса;
  • ClassName – имя класса, который содержит методы оперирования обобщенным типом класса.

Общая форма объявления объекта шаблонного класса имеет следующий вид:

ClassName <type> objName;

где

  • ClassName – имя шаблонного класса;
  • type – конкретный тип данных в программе;
  • objName – имя объекта (экземпляра) класса.

Ключевое слово class может быть заменено на слово typename. В этом случае общая форма объявления шаблонного класса может быть следующей:

template <typename T>
class ClassName 
{
    // тело класса 
    // ... 
}

В данном случае нет разницы между использованием слов class и typename.

3. Какие преимущества дает использование шаблонов классов?

Объявление шаблона класса дает следующие преимущества:

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





4. Пример объявления шаблона класса, который содержит методы обработки числа, тип которого может быть целым или вещественным

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

В примере объявляется шаблон класса, содержащий методы, которые выполняют следующие операции над некоторым числом:

  • умножение числа на 2;
  • деление одного числа на другое. Для целых типов выполняется деление нацело;
  • возведение числа в квадрат (степень 2).

Объявление шаблона имеет вид

// шаблон класса, реализующего число разных типов
template <class T>
class MyNumber
{
    public:
    // конструктор
    MyNumber(void) { }

    // метод, умножающий число на 2
    void Mult2(T* t);

    // метод, возвращающий квадрат числа для некоторого типа T
    T MySquare(T);

    // метод, который делит два числа типа T и возвращает результат типа T
    T DivNumbers(T, T);
};

// реализация метода, умножающего число на 2
template <class T> void MyNumber<T>::Mult2(T* t)
{
    *t = (*t)*2;
}

// реализация метода, возвращающего квадрат числа
template <class T> T MyNumber<T>::MySquare(T number)
{
    return (T)(number*number);
}

// метод, который делит 2 числа и возвращает результат от деления
template <class T> T MyNumber<T>::DivNumbers(T t1, T t2)
{
    return (T)(t1/t2);
}

Использование шаблона класса MyNumber в другом программном коде

MyNumber <int> mi; // объект mi класса работает с типом int
MyNumber <float> mf; // объект mf работает с типом float

int d = 8;
float x = 9.3f;

// умножение числа на 2
mi.Mult2(&d); // d = 16
mf.Mult2(&x); // x = 18.6

// возведение числа в квадрат
int dd;
dd = mi.MySquare(9); // dd = 81 - целое число

double z;
z = mf.MySquare(1.1); // z = 1.21000... - вещественное число

// деление чисел
long int t;
float f;

t = mi.DivNumbers(5, 2); // t = 2 - деление целых чисел
f = mf.DivNumbers(5, 2); // f = 2.5 - деление вещественных чисел

5. Общая форма объявления шаблона класса, принимающего аргументы

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

Общая форма шаблона класса, содержащего аргументы, следующая:

template <class T, type1 var1, type2 var2, ..., typeN varN> class ClassName
{
    // тело шаблона класса
    // ...
}

где

  • T – некоторый обобщенный тип данных;
  • type1, type2, …, typeN – конкретные типы аргументов с именами var1, var2, …, varN;
  • var1, var2, …, varN – имена аргументов, которые используются в шаблоне класса.

Общая форма объявления объекта шаблонного класса, содержащего один аргумент:

ClassName <type, arg> objName;

где

  • ClassName – имя шаблонного класса;
  • type – конкретный тип данных, для которого формируется реальный класс;
  • arg – значение аргумента, которое используется в шаблоне класса;
  • objName – имя объекта шаблонного класса.

6. Пример использования шаблона класса, принимающего два аргумента

В примере реализуется шаблон класса CMyArray, который содержит методы обработки массива чисел. Тип элементов массива может быть вещественным или целым.

Шаблон класса получает два целых числа:

  • count – число элементов массива. Используется при инициализации класса с помощью конструктора с 1 параметром;
  • num – число, служащее для проведения операций над массивом.

Эти числа используются в методах для выполнения операций над массивом. Шаблон класса содержит следующие данные и методы:

  • количество элементов массива n;
  • массив элементов (чисел) A заданной размерности (10);
  • метод Power(), реализующий возведение элементов массива A в степень num. Значение num есть входным параметром (аргументом);
  • метод CalcNum(), реализующий подсчет числа элементов, которые больше заданного параметра num.

Текст шаблона класса следующий:

// шаблон класса, получающего 2 параметра
template <class TT, int count, int num> class CMyArray
{
    private:
    int n; // число элементов массива
    TT A[10]; // массив элементов

    public:
    // конструктор класса без параметров
    CMyArray()
    {
        // число элементов берем из входного параметра count
        n = count;

        // заполнить массив произвольными значениями
        for (int i=0; i<n; i++)
            A[i] = (TT)(i*2);
    }

    // конструктор класса с 1 параметром
    CMyArray(int cnt)
    {
        if (cnt<=10) n = cnt;
        else n = 0;

        // заполнение массива произвольными значениями
        for (int i=0; i<n; i++)
            A[i] = (TT)(i*2);
    }

    // методы доступа
    int GetN(void) { return n; }

    void SetN(int n)
    {
        if (n<=10) this->n = n;
        else n=0;

        for (int i=0; i<n; i++)
            A[i] = (TT)(i*2);
    }

    // метод, возвращающий значение элемента массива с заданным индексом
    TT GetItem(int index) { return (TT)A[index]; }

    // методы, выполняющие операции над массивом A
    // возведение элементов массива в степень num
    void Power(void);

    // подсчет числа элементов, значения которых есть больше num
    int CalcNum(void);
};

// возведение значения элементов массива в степень num
template <class TT, int count, int num>
void CMyArray<TT, count, num>::Power(void)
{
    if (n<0) return;

    for (int i=0; i<n; i++)
        A[i] = System::Math::Pow(A[i], num);
}

// метод, определяющий число элементов массива,
// которые больше заданного числа num (num - входящий параметр)
template <class TT, int count, int num>
int CMyArray<TT, count, num>::CalcNum(void)
{
    int k = 0;

    // цикл подсчета
    for (int i=0; i<n; i++)
        if (A[i] > num)
            k++;
    return k;
}

Использование шаблона в некотором другом программном коде (функции, методе)

// использование шаблона класса CMyArray
// массив целых чисел, параметры: count=7, num=2
CMyArray <int, 7, 2> ai1;

// массив целых чисел, вызов конструктора с 1 параметром
CMyArray <int, 8, -3> ai2(6); // число элементов count = 6, num=-3

// массив вещественных чисел типа double, вызов конструктора без параметров
CMyArray <double, 4, 5> ad1;

// проверка
int n, t;
double x;

n = ai1.GetN(); // n = 7
n = ai2.GetN(); // n = 6
n = ad1.GetN(); // n = 4

// проверка массива
t = ai1.GetItem(3); // t = 6
t = ai2.GetItem(0); // t = 0
x = ad1.GetItem(2); // x = 4.0

// вызов методов обработки массива и проверка результата
ai1.Power(); // возведение элементов массива в степень num=2
t = ai1.GetItem(3); // t = 6^2 = 36

// подсчет числа элементов, которые больше чем -3
// всего в массиве класса ai2 6 элементов
t = ai2.CalcNum(); // t = 6

// работа с классом, реализующим тип double
x = ad1.GetItem(3); // x = 6.0
ad1.Power(); // возведение чисел массива x в степень num = 5
x = ad1.GetItem(3); // x = 6.0^5 = 7776


Связанные темы