Поняття шаблону класу. Ключове слово template. Переваги використання шаблонів. Приклади оголошеньта використання шаблонів класів. Аргументи в шаблонах

Поняття шаблону класу. Ключове слово template. Переваги використання шаблонів. Приклади оголошень та використання шаблонів класів. Аргументи в шаблонах


Зміст


1. Що називається шаблоном класу? Що таке шаблон класу?

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

Шаблон класу дозволяє оперувати даними різних типів у загальному. Тобто, немає прив’язки до деякого конкретного типу даних (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;
  • зменшення текстової частини програмного коду, і, як наслідок, підвищення читабельності програм;
  • забезпечення зручного механізму передачі аргументів у шаблон класу з метою їх обробки методами класу.


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, що є вхідним параметром (аргументом);
  • метод 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);

    // підрахунок кількості елементів, що є більше заданого аргументу
    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(); // піднести усі числа масиву до степеня num = 5
x = ad1.GetItem(3); // x = 6.0^5 = 7776


Зв’язані теми