Требования к фактическим параметрам шаблона

Шаблоны (параметризованные типы)

Цель работы: повторить представление и правила работы с шаблонами в С++.

 

Порядок выполнения лабораторной работы

1. Изучить теоретические сведения. Разобрать представленные примеры.

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

3. Реализовать полученные задания. Любое общение с пользователем должно сопровождаться поясняющимся текстом. Также в программе должно быть реализовано минимум 2 исключительных ситуации. Исключительные ситуации должны обрабатываться в отдельном классе. Обязательна оконная (формочная) реализация программы с использованием элементов управления.

4. Показать результат работы программы преподавателю.

5. Защитить лабораторную работу.

Требования к отчету

Отчет должен содержать:

1. Цель работы.

2. Задание.

3. Словесное описание исключительных ситуаций.

4. UML диаграмма классов.

5. Текст программы на языке C++ с комментариями.

6. Тесты (копии выходных форм программы/сформированных файлов). Следует указать для каких типов и какие операции проверены и какие выявлены ошибки (или не выявлены).

7. Выводы.

 

Теоретические сведения

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

Ранее мы дублировали и размножали части программ, используя простое, но эффективное средство - текстовый редактор. Сегодня С++ предлагает нам более совершенный способ дублирования, и имя ему - "шаблоны".

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

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

В языке С++ имеются два типа шаблонов - шаблоны функций и шаблоны классов.

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

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

// Описание шаблона функции

template <class X>

X min (X a, X b)

{ return a<b? a: b;

}

Ключевое слово class в описании шаблона означает тип, идентификатор в списке параметров шаблона X означает имя любого типа.

В описании заголовка функции этот же идентификатор означает тип возвращаемого функцией значения и типы параметров функции.

...

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

int m = min (1, 2);

...

Экземпляр шаблона функции порождается (генерируется) компилятором

int min (int a, int b)

{ return a<b? a: b;

}

В списке параметров шаблона слово class может также относится к обычному типу данных. Таким образом, список параметров шаблона <class T> просто означает, что Т представляет собой тип, который будет задан позднее. Так как Т является параметром, обозначающим тип, шаблоны иногда называют параметризованными типами.

Приведем описание шаблона функции

template <class T>

T toPower (T base, int exponent)

{ T result = base;

if (exponent==0) return (T)1;

if (exponent<0) return (T)0;

while (--exponent) result *= base;

return result;

}

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

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

int i = toPower (10, 3);

long l = toPower (1000L, 4);

double d = toPower (1e5, 5);

В первом примере Т становится типом int, во втором - long. Наконец, в третьем примере Т становится типом double. Следующий пример приведет к ошибке компиляции, так как в нем принимающая переменная и возвращаемое значение имеют разные типы:

int i = toPower (1000L, 4);

Требования к фактическим параметрам шаблона

Шаблон функции toPower() может быть использован почти для любого типа данных. Предостережение "почти" проистекает из характера операций, выполняемых над параметром base и переменной result в теле функции toPower(). Какой бы тип мы ни использовали в функции toPower(), эти операции для нее должны быть определены. В противном случае компилятор не будет знать, что ему делать. Вот список действий, выполняемых в функции toPower() с переменными base и result:

  1. T result = base;
  2. return (T)1;
  3. return (T)0;
  4. result *= base;
  5. return result;

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

- действие 1 инициализирует объект типа Т таким образом, что класс Т должен содержать конструктор копирования,

- действия 2 и 3 преобразуют значения типа int в объект типа Т, поэтому класс Т должен содержать конструктор с параметром типа int, поскольку именно таким способом в классах реализуется преобразование к классовым типам,

- действие 4 использует операцию *= над типом Т, поэтому класс должен содержать собственную функцию-operator *=().

- действие 5 предполагает, что в типе T предусмотрена возможность построения безопасной копии возвращаемого объекта (см. конструктор копирования).

Схема такого класса выглядит следующим образом:

class T

{ public:

T (const T &base); // конструктор копирования

T (int i); //приведение int к Т

operator *= (T base);

//... прочие методы

}

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


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



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