Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab_33.doc
Скачиваний:
13
Добавлен:
16.11.2019
Размер:
88.58 Кб
Скачать

Вимоги до фактичних параметрів шаблону

Шаблон функції toPower() може бути використаний майже для будь-якого типу даних. Застереження "майже" виникає з характеру операцій, що виконуються над параметром base і змінній result в тілі функції toPower(). Який би тип ми не використали у функції toPower(), ці операції для неї мають бути визначені. Інакше компілятор не знатиме, що йому робити. Ось список дій, що виконуються у функції toPower() із змінними base і result, :

  1. T result = base;

  2. return #001;

  3. return #000;

  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);

// ... // .. інші методи

}

Використовуючи класи в шаблонах функцій, переконаєтеся в тому, що ви знаєте, які дії з ними виконуються в шаблоні функції, і чи визначені для класу ці дії. Якщо ви не забезпечили клас необхідними функціями, виникнуть різні незрозумілі повідомлення про помилки.

Ототожнення типів аргументів

Оскільки компілятор генерує екземпляри шаблонів функцій згідно з типами, заданими при їх викликах, то критичним моментом є передача коректних типів, особливо якщо шаблон функції має два або більш за параметри. Хорошим прикладом є класична функція max() :

template <class T>

T max (T a, T b)

{ return a > b ? a: b;

}

Функція max() працюватиме правильно, якщо обидва її аргументи мають один і той же тип:

int i = max (1, 2);

double d = max (1.2, 3.4);

Проте, якщо аргументи різних типів, то виклик max() приведе до помилки, оскільки компілятор не зможе зрозуміти, що йому робити.

Один з можливих способів для дозволу неоднозначності полягає у використанні приведення типів, щоб прояснити наші наміри:

int i = max ((int)'a ', 100);

Друга можливість - це явно оголосити версію екземпляра шаблону функції перед її викликом:

int max (int, int);

int j = max ('a ', 100);

Третій спосіб розв'язати проблему полягає в створенні шаблону функцій, який має параметри різних типів.

template <class T1, class T2>

T1 max (T1 a, T2 b)

{ return a > (T1) b ? a: (T1) b;

}

Використання цієї нової версії max() не приведе до неоднозначності у разі використання двох різних типів. Наприклад, якщо написати

max ('a ', 100);

те компілятор використовуватиме два заданих (за допомогою аргументів типу) і побудує версію функції max() із заголовком

char max (char, int);

Далі компілятор перед виконанням порівняння приведе тип другого аргументу до типу першого аргументу. Такий спосіб допустимий, проте використання двох типових параметрів в шаблоні функції, яка повинна була б працювати тільки з одним типом, часто лише утрудняє життя. Досить важко пам'ятати, що

max ('a ', 100)

дає значення типу char, тоді як

max (100, 'a')

передає в зухвалу програму int.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]