C++. Примеры реализации шаблонных функций и перегруженных шаблонных функций. Обработка одиночных элементов. Обработка массивов

Примеры реализации шаблонных функций и перегруженных шаблонных функций. Обработка одиночных элементов. Обработка массивов

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


Содержание


1. Примеры реализаций шаблонных функций

1.1. Пример шаблонной функции поиска максимума между двумя элементами

В примере реализован шаблон функции Max() (шаблонной функции) для обобщенного типа T, которая определяет максимальное значение между двумя параметрами a и b.

#include <iostream>
using namespace std;

// Тема. Шаблонные функции
// Шаблон функции поиска максимального значения между двумя значениями
template <class T>
T Max(T a, T b)
{
  if (a > b) return a;
  return b;
}

void main()
{
  // Демонстрация шаблонной функции Max()
  // 1. Для типів int
  int i1, i2, maxInt;

  // 1.1. Ввод целых чисел i1, i2
  cout << "Enter integers:" << ::endl;
  cout << "i1 = ";
  cin >> i1;
  cout << "i2 = ";
  cin >> i2;

  // 1.2. Вызов шаблонной функции Max(T, T) => Max(int, int)
  maxInt = Max(i1, i2);

  // 1.3. Вывод результата
  cout << "maxInt = " << maxInt << endl;

  // 2. Для типов float
  float f1, f2, maxFloat;

  // 2.1. Ввод чисел f1, f2
  cout << "Enter floats:" << ::endl;
  cout << "f1 = ";
  cin >> f1;
  cout << "f2 = ";
  cin >> f2;

  // 2.2. Вызов шаблонной функции Max(T, T) => Max(float, float)
  maxFloat = Max(f1, f2);

  // 2.3. Вывод результата
  cout << "maxFloat = " << maxFloat << endl;

  // 3. Для типов char
  char c1, c2, maxChar;

  // 3.1. Ввод значений c1, c2
  cout << "Enter chars:";
  cout << "\nc1 = ";
  cin >> c1;
  cout << "c2 = ";
  cin >> c2;

  // 3.2. Вызов шаблонной функции Max(T, T) => Max(char, char)
  maxChar = Max(c1, c2);

  // 3.3. Вывод результата
  cout << "maxChar = " << maxChar << endl;
  system("pause");
}

Результат работы программы:

Enter integers:
i1 = 2
i2 = 7
maxInt = 7
Enter floats:
f1 = 2.56
f2 = 3.55
maxFloat = 3.55
Enter chars:
c1 = f
c2 = q
maxChar = q

 

1.2. Пример шаблонной функции вычисления среднего арифметического значений элементов массива

В примере разработана шаблонная функция Average() для поиска среднего арифметического значений двумерного массива.

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

Текст приложения, созданного по шаблону Console Application следующий.

#include <iostream>
using namespace std;

// Тема. Шаблоны функции

// Используется ключевое слово typename или class.
// Функция получает 2 параметра:
// - count - количество элементов в массиве Array[];
// - Array[] - массив элементов типа T.
template <typename T>
double Average(int count, T Array[])
{
  // 1. Объявить переменную avg типа double,
  //   поскольку среднее арифметическое буде вещественным числом
  double avg;

  // 2. Обнулить значение переменной avg перед суммированием
  avg = 0.0;

  // 3. Вычислить сумму элементов массива Array[]
  for (int i = 0; i < count; i++)
    avg += Array[i];

  // 4. Вычислить среднее арифметическое
  avg /= count;

  // 5. Вернуть значение avg
  return avg;
}

void main()
{
  // Демонстрация шаблонной функции Average(int, T[])
  // 1. Для типов int
  // 1.1. Объявить переменные
  int countInt = 5; // количество элементов в массиве AI
  int AI[] = { 2, 4, -1, 70, 18 }; // инициализация массива AI
  double avg; // среднее арифметическое - результат

  // 1.2. Вызов шаблонной функции Average(int, T[]) => Average(int, int[])
  avg = Average(countInt, AI);

  // 1.3. Вывод результата
  cout << "Average for AI = " << avg << endl;

  // 2. Для типов float
  // 2.1. Объявить переменные
  int countFloat = 6;
  float AF[] = { 2.8f, 3.2f, -1.4f, 0.5f , 1.2f, 10.2f };

  // 2.2. Вызов шаблонной функции Average(int, T[]) => Average(int, float[])
  avg = Average(countFloat, AF);

  // 2.3. Вывод результата
  cout << "Average for AF = " << avg << endl;
  system("pause");
}

Результат работы программы

Average for AI = 18.6
Average for AF = 2.75

 

1.3. Пример реализации шаблонных функций копирования массива и вывода массива на экран

Задача. Написать шаблон функции CopyArray(), копирующей элементы одномерного массива A[] в массив B[]. Размеры массивов считать одинаковыми. Вывод результирующего массива реализовать в шаблонной функции Print().

Текст программного решения следующий.

#include <iostream>
using namespace std;

// Шаблон функции CopyArray().
// Функция копирует один массив в другоай: A[]=>B[]
// Параметры:
// - count - количество элементов в массивах;
// - A[] - массив-источник, элементы массива имеют тип Type;
// - B[] - массив-назначение, элементы массива имеют тип Type.
template <class Type>
void CopyArray(int count, Type A[], Type B[])
{
  for (int i = 0; i < count; i++)
  {
    B[i] = A[i];
  }
}

// Шаблон функции Print().
// Функция выводит массив обобщенного типа TT на экран
// Параметры:
// - count - количество элементов в массиве;
// - Array[] - массив элементов типа TT.
template <class TT>
void Print(int count, TT Array[])
{
  cout << "Items of array:" << ::endl;
  for (int i = 0; i < count; i++)
  {
    cout << Array[i] << "\t";
  }
  cout << endl;
}

void main()
{
  // Использование шаблонной функции CopyArray()
  // 1. Объявить общую константу
  const int MAX_ITEMS = 10;

  // 2. Демонстрация для типа int
  // 2.1. Объявить два массива типа int
  int AI[] = { 1, -3, 2, 4, 5 }; // массив-источник
  int BI[MAX_ITEMS]; // масив-назначение

  // 2.2. Вызов шаблонной функции CopyArray()
  CopyArray(5, AI, BI);

  // 2.3. Вызов шаблонной функции Print()
  cout << "Array BI[]. ";
  Print(5, BI);

  // 3. Демонстрация для типа float
  // 3.1. Объявить два массива типа float
  float AF[] = { -2.4, 3.8, -1.5, 7.75 };
  float BF[MAX_ITEMS];

  // 3.2. Вызов шаблонной функции CopyArray()
  CopyArray(4, AF, BF);

  // 3.3. Вызов шаблонной функции Print()
  cout << "Array BF[]. ";
  Print(4, BF);
}

Результат работы программы

Array BI[]. Items of array:
1       -3       2       4       5
Array BF[]. Items of array:
-2.4   3.8     -1.5   7.75

 



2. Примеры реализаций перегруженных шаблонных функций

2.1. Пример перегрузки шаблонной функции поиска максимума между 2, 3, 4 параметрами

В примере реализована перегрузка шаблонной функции Max(), находящей максимальное значение между получаемыми параметрами. Функция реализована для двух, трех и 4 параметров.

Текст демонстрационной программы следующий:

#include <iostream>
using namespace std;

// Тема. Перегрузка шаблонов функций

// Перегрузка шаблонной функции с именем Max().
// 1. Шаблон функции Max(T, T),
//   определяющей максимум между 2 параметрами
template <class T>
T Max(T a, T b)
{
  if (a > b) return a;
  return b;
}

// 2. Шаблон функции Max(T, T, T),
//   определяющей максимум между 3 параметрами
template <class T>
T Max(T a, T b, T c)
{
  T maximum = a;
  if (maximum < b)
    maximum = b;
  if (maximum < c)
    maximum = c;
  return maximum;
}

// 3. Шаблон функции Max(T, T, T),
//   определяющей максимум между 4 параметрами
template <class T>
T Max(T a, T b, T c, T d)
{
  T maximum = a;
  if (maximum < b) maximum = b;
  if (maximum < c) maximum = c;
  if (maximum < d) maximum = d;
  return maximum;
}

void main()
{
  // Демонстрация перегруженной шаблонной функции Max()
  // 1. Для двух параметров
  int i1, i2, maxInt_2;

  // 1.1. Ввод целых чисел i1, i2
  cout << "Enter integers:" << ::endl;
  cout << "i1 = ";
  cin >> i1;
  cout << "i2 = ";
  cin >> i2;

  // 1.2. Вызов шаблонной функции Max(T, T) => Max(int, int)
  maxInt_2 = Max(i1, i2);

  // 1.3. Вывод результата
  cout << "maxInt = " << maxInt_2 << endl;

  // 2. Для 3-х параметров типа float
  float f1, f2, f3, maxFloat_3;

  // 2.1. Ввод чисел f1, f2, f3
  cout << "Enter floats:" << ::endl;
  cout << "f1 = ";
  cin >> f1;
  cout << "f2 = ";
  cin >> f2;
  cout << "f3 = ";
  cin >> f3;

  // 2.2. Вызов шаблонной функции Max(T, T, T) => Max(float, float, float)
  maxFloat_3 = Max(f1, f2, f3);

  // 2.3. Вывод результата
  cout << "maxFloat = " << maxFloat_3 << endl;

  // 3. Для 4-х параметров типа double
  double d1, d2, d3, d4, maxDouble;

  // 3.1. Ввод значений d1, d2, d3, d4
  cout << "Enter doubles:";
  cout << "\nd1 = ";
  cin >> d1;
  cout << "d2 = ";
  cin >> d2;
  cout << "d3 = ";
  cin >> d3;
  cout << "d4 = ";
  cin >> d4;

  // 3.2. Вызов шаблонной функции Max(T, T, T, T)
  //     Max(T, T, T, T) => Max(double, double, double, double)
  maxDouble = Max(d1, d2, d3, d4);

  // 3.3. Вывод результата
  cout << "maxDouble = " << maxDouble << endl;
  system("pause");
}

Результат работы программы:

Enter integers:
i1 = 2
i2 = 5
maxInt = 5
Enter floats:
f1 = 2.56
f2 = 3.8
f3 = 4.44
maxFloat = 4.44
Enter doubles:
d1 = 2.96
d2 = 1.35
d3 = 2.88
d4 = 3.54
maxDouble = 3.54

 

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

 

#include <iostream>
using namespace std;

// Перегрузка шаблона функции (шаблонной функции).

// Объявить глобальные константы границ статического массива
const int MAX_ITEMS_1 = 10;
const int MAX_ITEMS_2 = 10;
const int MAX_ITEMS_3 = 10;

// Функция CountItems() определяет количество положительных элементов.
// 1. Реализация для одномерного массива
template <typename T>
int CountItems(int n, T Array[])
{
  int count = 0; // результат

  // цикл вычисления count
  for (int i = 0; i < n; i++)
    if (Array[i] > 0)
      count++;

  // вернуть результат
  return count;
}

// 2. Реализация для двумерного массива
// Параметры:
// - m, n - размеры массива
// - Array - двумерный массив
template <class Type>
int CountItems(int m, int n, Type Array[][MAX_ITEMS_2])
{
  int count = 0; // результат

  // вложенные циклы вычисления k
  for (int i = 0; i < m; i++)
    for (int j = 0; j < n; j++)
      if (Array[i][j] > 0)
        count++;

  // возврат результата
  return count;
}

// 3. Реализация для трехмерного массива
// Параметры:
// - m, n - размеры массива
// - Array - трехмерный массив
template <class T>
int CountItems(int m, int n, int d, T Array[][MAX_ITEMS_2][MAX_ITEMS_3])
{
  int count = 0; // результат

  // цикл вычисления count
  for (int i = 0; i < m; i++)
    for (int j = 0; j < n; j++)
      for (int k = 0; k < d; k++)
        if (Array[i][j][k] > 0)
          count++;

  // вернуть результат
  return count;
}

void main()
{
  // Демонстрация перегруженной шаблонной функции CountItems()
  // 1. Для одномерного массива типа double
  // 1.1. Объявить внутренние переменные
  double AD[MAX_ITEMS_1] = { 2.5, -1.1, 3.5, 8.2 }; // инициализация массива
  int count1;

  // 1.2. Вызвать функцию CountItems(int, double[])
  count1 = CountItems(4, AD); // count1 = 3

  // 1.3. Вывести результат
  cout << "count1 = " << count1 << endl;

  // 2. Для двумерного массива типа short
  // 2.1. Объявить внутренние переменные
  short AS[MAX_ITEMS_1][MAX_ITEMS_2] =
  {
    { 3, 5, 2},
    { 4, 2,-5},
    {-1,-2,-3},
    { 5,-8,-4}
  };
  int count2;

  // 2.2. Вызвать функцию CountItems(int, int, short[][])
  count2 = CountItems(4, 3, AS);

  // 2.3. Вывести результат
  cout << "count2 = " << count2 << endl;

  // 3. Для трехмерного массива типа float. Размер массива 2*3*4
  // 3.1. Объявить внутренние переменные
  float AF[MAX_ITEMS_1][MAX_ITEMS_2][MAX_ITEMS_3]
  {
    {
      {   1.2f, -2.3f, -4.4f,  2.5f },
      {   4.2f, -3.3f, -1.8f, -0.1f },
      {  -1.8f, -2.5f,  3.3f,  4.2f }
    },
    {
      {   4.8f, -1.2f,  3.5f, 8.8f },
      {   1.1f,  0.5f,  0.8f, 2.5f },
      {   4.6f,  1.3f, -2.2f, 1.8f }
    }
  };
  int count3;

  // 3.2. Вызвать функцию CountItems(int, int, int, float[][][])
  count3 = CountItems(2, 3, 4, AF);

  // 3.3. Вывести результат
  cout << "count3 = " << count3 << endl;
}

Результат работы программы

count1 = 3
count2 = 6
count3 = 15

 

2.3. Пример перегрузки шаблонной функции, формирующей динамические массивы разных размерностей

Задача. Написать перегруженную шаблонную функцию FormArray(), которая заполняет одномерный и двумерный динамические массивы случайными элементами. Вывод элементов массивов реализовать с помощью перегруженной шаблонной функции PrintArray(), которая также имеет две реализации: для одномерных и двумерных массивов.

Текст программы, созданной по шаблону Console Application следующий:

#include <iostream>
#include <time.h>
using namespace std;

// Перегрузка шаблонной функции FormArray()

// 1. Формирование одномерного массива
// Параметры:
// - count - количество элементов в массиве;
// - Array[] - массив элементов типа T.
template <class T>
void FormArray(int count, T* Array)
{
  // 1. Инициализировать генератор случайных чисел
  srand(time(NULL));

  // 2. Записать в массив случайные числа от 0 до 100
  for (int i = 0; i < count; i++)
    Array[i] = (T)(rand() % 101);
}

// 2. Формирование двумерного массива
// Параметры:
// - m, n - размеры массива;
// - Array - двумерный массив элементов типа T
template <class T>
void FormArray(int m, int n, T** Array)
{
  // 1. Инициализировать данные
  srand(time(NULL));

  // 2. Заполнить массив случайными значениями
  for (int i = 0; i < m; i++)
    for (int j = 0; j < n; j++)
      Array[i][j] = (T)(rand() % 101);
}

// Перегруженная шаблонная функция вывода массива на экран
// 1. Реализация для одномерного массиву
template <class T>
void PrintArray(int count, T* A)
{
  cout << "Items of one-dimensional array: " << endl;
  for (int i = 0; i < count; i++)
    cout << A[i] << "\t";
  cout << endl;
}

// 2. Реализация для двумерного массива типа T
// Параметры:
// - m, n - размерность массива;
// - A - двумерный массив, элементы которого имеют тип T
template <class T>
void PrintArray(int m, int n, T** A)
{
  cout << "Items of two-dimensional array: " << endl;
  for (int i = 0; i < m; i++)
  {
    for (int j = 0; j < n; j++)
      cout << A[i][j] << "\t";
    cout << endl;
  }
}

void main()
{
  // Демонстрация перегрузки шаблонных функций

  // 1. Одномерный массив типа int
  // 1.1. Объявить динамический массив целых чисел и его размерность
  int* AI = nullptr;
  int count1;

  // 1.2. Ввести размер массива
  cout << "count = ";
  cin >> count1;

  try
  {
    // 1.3. Попытка выделить память для массива
    AI = new int[count1];
  }
  catch (bad_alloc ba)
  {
    // Если память не выделена, то выйти из программы
    // ba.what() - текст системной ошибки выделения памяти
    cout << "Error. " << ba.what() << endl;
    return;
  }

  // 1.4. Если память выделена удачно,
  //       то вызвать шаблонную функцию формирования элементов массива
  FormArray(count1, AI);

  // 1.5. Распечатать массив на экране
  PrintArray(count1, AI);

  // 1.6. После окончания работы освободить память для массива AI
  if (AI!=nullptr) delete[] AI;

  // 2. Демонстрация вызова FormArray() та PrintArray()
  //     для двумерного массива типа double
  // 2.1. Объявить переменные
  double** AD = nullptr; // двумерный массив
  int m, n; // размерность массива

  // 2.2. Ввести размер массива
  cout << "Enter the size of array: " << endl;
  cout << "m = ";
  cin >> m;
  cout << "n = ";
  cin >> n;

  // 2.3. Выделить память для массива AD
  try
  {
    // Попытка выделить память
    // для массива указателей на тип double
    AD = (double**) new double*[m];

    // для каждого элемента массива
    for (int i = 0; i < m; i++)
      AD[i] = new double[n];
  }
  catch (bad_alloc ba)
  {
    cout << "Error. " << ba.what() << endl;
    return;
  }

  // 2.4. Вызвать функцию FormArray(int, int, T**) => FormArray(int, int, double**)
  FormArray(m, n, AD);

  // 2.5. Вызвать функцию PrintArray(int, int, T**) => PrintArray(int, int, double**)
  PrintArray(m, n, AD);

  // 2.6. Освободить ранее выделенную память
  if (AD != nullptr)
    delete[] AD;
}

Результат работы программы

count = 4
Items of one-dimensional array:
97     40       23     95
Enter the size of array:
m = 5
n = 6
Items of two-dimensional array:
9       64       86     64     27       55
59     38       100     4       3       74
26     25       22     7       45       62
89     84      48     48     79     56
79     42       49     70     7       73

 


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