Создание простого шаблона функции 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Создание простого шаблона функции



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

template<class Т> Т mах(Т а, Т b)

{
if (а > b) return(а);
else return(b);
}

Буква T данном случае представляет собой общий тип шаблона. После определения шаблона внутри вашей программы вы объявляете прототипы функций для каждого требуемого вам типа. В случае шаблона тах следующие прототипы создают функции типа float и int.

float max(float, float);
int max(int, int);

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

template<class Т> Т max(Т а, Т b)

{
if (a > b) return(а);
else return(b);
}

float max(float a, float b)

{
if (a > b) return(a);
else return(b);
}

Следующая программа МАХ_ТЕМР.СРР использует шаблон тах для создания функции типа int и float.

#include <iostream.h>

template<class T> Т mах(Т а, Т b)

{
if (a > b) return(a);
else return(b);
}

float max(float, float);

int max(int, int);

void main(void)

{
cout << "Максимум 100 и 200 равен " << max(100, 200) << endl;
cout << "Максимум 5.4321 и 1.2345 равен " << max(5.4321, 1.2345) << endl;
}

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

Использование шаблонов функций

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

ШАБЛОНЫ, КОТОРЫЕ ИСПОЛЬЗУЮТ НЕСКОЛЬКО ТИПОВ

Предыдущее определение шаблона для функции max использовало единственный общий тип Т. Очень часто в шаблоне функции требуется указать несколько типов. Например, следующие операторы создают шаблон для функции show_array, которая выводит элементы массива. Шаблон использует тип Т для определения типа массива и тип Т1 для указания типа параметра count:

template<class T,class T1> void show_array(T *array,T1 count)

{
T1 index;
for (index =0; index < count; index++) cout << array[index] << ' ';
cout << endl;
}

Как и ранее, программа должна указать прототипы функций для требуемых типов:

void show_array(int *, int);
void show_array(float *, unsigned);

Следующая программа SHOW_TEM.CPP использует шаблон для создания функций, которые выводят массивы типа int и типа float.

#include <iostream.h>

template<class T,class T1> void show_array(T *array,T1 count)

{
T1 index;
for (index =0; index < count; index++) cout << array[index] “ ' ';
cout << endl;
}

void show_array(int *, int);

void show_array(float *, unsigned);

void main(void)

{
int pages[] = { 100, 200, 300, 400, 500 };
float pricesH = { 10.05, 20.10, 30.15 };
show_array(pages, 5);
show_array(prices, 3);
}

Шаблоны и несколько типов

По мере того как шаблоны функций становятся более сложными, они могут обеспечить поддержку нескольких типов. Например, ваша программа может создать шаблон для функции с именем array_sort, которая сортирует элементы массива. В данном случае функция может использовать два параметра: первый, соответствующий массиву, и второй, соответствующий количеству элементов массива. Если программа предполагает, что массив никогда не будет содержать более 32767 значений она может использовать тип int для параметра размера массива. Однако более универсальный шаблон мог бы предоставить программе возможность указать свой собственный тип этого параметра, как показано ниже:

template<class Т, class T1> void array_sort(T array[], T1 elements)

{
// операторы
}

С помощью шаблона array_sort программа может создать функции которые сортируют маленькие массивы типа float (менее 128 элементов) и очень большие массивы типа int, используя следующие прототипы:

void array_sort(float, char);
void array_sort(int, long);

ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ

Как вы уже знаете, использование шаблонов функций уменьшает объем программирования, позволяя компилятору C++ генерировать операторы для функций, которые отличаются только типами возвращаемых значений и параметров. Из урока 30 вы узнаете, как использовать шаблоны для создания типонезависимых, или общих, классов. До изучения урока 30 убедитесь, что вы освоили следующие основные концепции:

    1. Шаблоны функций позволяют вам объявлять типонезависимые, или общие, функции.
    2. Когда вашей программе требуется использовать функцию с определенными типами данных, она должна указать прототип функции, который определяет требуемые типы.
    3. Когда компилятор C++ встретит такой прототип функции, он создаст операторы, соответствующие этой функции, подставляя требуемые типы.
    4. Ваши программы должны создавать шаблоны для общих функций, которые работают с отличающимися типами. Другими словами, если вы используете с какой-либо функцией только один тип, нет необходимости применять шаблон.
    5. Если функция требует несколько типов, шаблон просто назначает каждому типу уникальный идентификатор, например Т, T1 и Т2. Позже в процессе компиляции компилятор C++ корректно назначит типы, указанные вами в прототипе функции.

 

 

УРОК 30. ИСПОЛЬЗОВАНИЕ ШАБЛОНОВ КЛАССОВ

Из урока 29 вы узнали, как в C++ использовать шаблоны функций для создания общих, или типонезависимых, функций. Определяя шаблоны функций вы заставляете компилятор C++ создавать в случае необходимости функции, которые отличаются типом возвращаемого значения или типами параметров. Если возникает необходимость создавать подобные функции, отличающиеся только используемыми типами, то может возникнуть необходимость и создания общих классов. А если так, то ваши программы могут определять шаблоны классов. В этом уроке рассмотрены действия вашей программы, необходимые для объявления и дальнейшего использования шаблонов классов. К концу данного урока вы освоите следующие основные концепции:

  • Используя ключевое слово template и символы типов (например, Т, T1 и Т2) ваши программы могут создать шаблон класса — определение шаблона класса может использовать эти символы для объявления элементов данных, указания типов параметров и возвращаемого значения функций-элементов и т.д.
  • Для создания объектов класса с использованием шаблонов ваши программы просто ссылаются на имя класса, за которым внутри угловых скобок следуют типы (например, <int, float>), каждому из которых компилятор назначает символы типов и имя переменной.
  • Если у класса есть конструктор, с помощью которого вы инициализируете элементы данных, вы можете вызвать этот конструктор при создании объекта с использованием шаблона, например class_name<int,float>values(200);.
  • Если компилятор C++ встречает объявление объекта, он создает класс из шаблона, используя соответствующие типы.

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

СОЗДАНИЕ ШАБЛОНА КЛАССА

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

class array

{
public:
array(int size);
long sum(void);
int average_value(void);
void show_array(void);
int add_value(int);
private:
int *data;
int size;
int index;
};

Следующая программа I_ARRAY.CPP использует класс array ддя работы со значениями типа int.

#include <iostream.h>

#include <stdlib.h>

class array

{
public:
array(int size);
long sum(void);
int average_value(void);
void show_array(void);
int add_value(int);
private:
int *data;
int size;
int index;
};

array::array(int size)

{
data = new int [size];
if (data == NULL)

{
cerr << "Недостаточно памяти - программа завершается " << endl;
exit(l);
}

array:: size = size;
array::index = 0;
}

long array::sum(void)

{
long sum = 0;
for (int i = 0; i < index; i++) sum += data[i];
return(sum);
}

int array::average_value(void)

{
long sum = 0;
for (int i = 0; i < index; i++) sum += data[i];
return (sum / index);
}

void array::show_array(void)

{
for (int i = 0; i < index; i++) cout << data[i] << ' ';
cout << endl;
}

int array::add_value(int value)

{
if (index == size) return(-1); // массив полон
else

{
data[index] = value;
index++;
return(0); // успешно
}
}

void main(void)

{
array numbers (100); // массив из 100 эл-тов
int i;
for (i = 0; i < 50; i++) numbers.add_value(i);
numbers.show_array();
cout << "Сумма чисел равна " << numbers.sum () << endl;
cout << "Среднее значение равно " << numbers.average_value() << endl;
}

Как видите, программа распределяет 100 элементов массива, а затем заносит в массив 50 значений с помощью метода add_value. В классе array переменная index отслеживает количество элементов, хранимых в данный момент в массиве. Если пользователь пытается добавить больше элементов, чем может вместить массив, функция add_value возвращает ошибку. Как видите, функция average_value использует переменную index для определения среднего значения массива. Программа запрашивает память для массива, используя оператор new, который подробно рассматривается в уроке 31.

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

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

Пойдем дальше. Теперь предположим, что вашей программе необходимо работать с массивом значений с плавающей точкой, кроме того, что она работает с целочисленным массивом. Один из способов обеспечить поддержку массивов различных типов состоит в создании разных классов. С другой стороны, используя шаблоны классов, вы можете избавиться от необходимости дублировать классы. Ниже представлен шаблон класса, который создает общий класс array:

template<class T, class T1> class array

{
public:
array(int size);
T1 sum (void);
T average_value(void);
void show_array(void);
int add_value(T);
private:
T *data;
int size;
int index;
};

Этот шаблон определяет символы типов T и T1. В случае массива целочисленных значений Т будет соответствовать int, а T1 — long. Аналогичным образом для массива значений с плавающей точкой значения Т и Т1 равны float. Теперь потратьте время, чтобы убедиться, что вы поняли, как компилятор С++ будет подставлять указанные вами типы вместо символов Т и Т1.

Далее, перед каждой функцией класса вы должны указать такую же запись со словом template. Кроме того, сразу же после имени класса вы должны указать типы класса, например array <T, T1>::average_value. Следующий оператор иллюстрирует определение функции average_value для этого класса:

template<class Т, class T1> Т array<T, T1>::average_value(void)

{
T1 sum = 0;
int i;
for (i = 0; i < index; i++) sum += data[i];
return (sum / index);
}

После создания шаблона вы можете создавать класс требуемого типа, указывая имя класса, а за ним в угловых скобках необходимые типы, как показано ниже:

Имя шаблона //----> array <int, long> numbers (100); <------//Типы шаблона
array <float, float> values(200);

Программа GENARRAY.CPP использует шаблон класса array для создания двух классов, один из которых работает со значениями типа int, а второй — со значениями типа float.

#include <iostream.h>

#include <stdlib.h>

template<class T, class T1> class array

{
public:
array(int size);
T1 sum(void);
T average_value(void);
void show_array(void);
int add_value(T);
private:
T *data;
int size;
int index;
};

template<class T, class T1> array<T, t1>::array(int size)

{
data = new T[size];
if (data == NULL)

{
cerr << "Недостаточно памяти - программа завершается" << endl;
exit(l);
}

array::size = size;
array::index = 0;
}

template<class T, class T1> Tl array<T, Tl>::sum(void)

{
T1 sum = 0;
for (int i = 0; i < index; i++) sum += data[i];
return(sum);
}

template<class T, class T1> T array<T, T1>::average_value(void)

{
Tl sum =0;
for (int i = 0; i < index; i++) sum += data[i];
return (sum / index);
}

template<class T, class T1> void array<T, T1>::show_array(void)

{
for (int i = 0; i < index; i++) cout << data[i] << ' ';
cout << endl;
}

template<class T, class T1> int array<T, T1>::add_value(T value)

{
if (index == size)
return(-1); // Массив полон
else

{
data[index] = value;
index++;
return(0); // Успешно
}
}

void main(void)

{
// Массив из 100 элементов
array<int, long> numbers(100)7
// Массив из 200 элементов
array<float, float> values(200);
int i;
for (i = 0; i < 50; i++) numbers.add_value(i);
numbers.show_array();
cout << "Сумма чисел равна " << numbers.sum () << endl;
cout << "Среднее значение равно " << numbers.average_value() << endl;
for (i = 0; i < 100; i++) values.add_value(i * 100);
values.show_array();
cout << "Сумма чисел равна." << values.sum() << endl;
cout << "Среднее значение равно " << values.average_value() << endl;
}

Лучшим способом понять шаблоны классов будет напечатать две копии этой программы. В первой копии замените все символы T и Т1 на int и long. A во второй замените Т и Т1 на float.



Поделиться:


Последнее изменение этой страницы: 2016-09-13; просмотров: 165; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.141.202.187 (0.032 с.)