Урок №186. Явна спеціалізація шаблону класу

  Юрій  | 

  Оновл. 10 Жов 2021  | 

 162

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

Розглянемо клас-масив, який може зберігати 8 об’єктів:

Оскільки це шаблон класу, то він працюватиме з будь-яким типом даних:

Результат:

0
1
2
3
4
5
6
7
false
true
true
true
true
false
true
true

Хоча все працює правильно, реалізація Repository8<bool>, насправді, не настільки ефективна, якою вона могла б бути. Оскільки всі змінні повинні мати адреси, а ЦП не може дати адресу чомусь меншому за 1 байт, то розмір всіх змінних повинен становити не менше 1 байту. Отже, кожна змінна типу bool займає цілий байт, хоча технічно їй потрібен тільки 1 біт для зберігання значення true або false! Таким чином, змінна типу bool — це 1 біт корисної інформації та 7 біт марно витраченого місця. Виходить, що наш клас Repository8<bool>, який має 8 змінних типу bool, фактично працює тільки з 1 байтом даних, а решта 7 байтів витрачаються даремно.

Вихід є: ми можемо “стиснути” 8 змінних типу bool в 1 байт, заощадивши при цьому решту 7 байтів. Однак для цього нам потрібно буде змінити реалізацію класу, замінивши масив з 8 змінних типу bool (8 байтів) на 1 змінну типу unsigned char (1 байт). Ми могли б, звичайно, використати для цього новий окремий клас, але це неефективно, і програмісту доведеться пам’ятати, що Repository8<T> працює з усіма типами даних, крім bool, а при роботі з bool слід викликати Repository8Bool (неважливо, яке ім’я буде у цього класу). Це зайва робота, яку можна уникнути, використовуючи явну спеціалізацію шаблону класу.

Спеціалізація шаблону класу

Спеціалізація шаблону класу (або «явна спеціалізація шаблону класу») дозволяє спеціалізувати шаблон класу для роботи з певним типом даних (або відразу з декількома типами даних, якщо є кілька параметрів шаблону).

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

Розглянемо спеціалізацію шаблону класу Repository8 для роботи з типом bool:

По-перше, починаємо з template<>. Ключове слово template повідомляє компілятору, що це шаблон, а порожні кутові дужки означають, що немає ніяких параметрів. А параметрів немає через те, що ми замінюємо єдиний параметр шаблону (T, який відповідає за тип даних) конкретним типом даних (bool). Потім ми пишемо ім’я класу і додаємо до нього <bool>, повідомляючи компілятору, що працюватимемо з типом bool.

Всі інші зміни — це просто деталі реалізації класу. Зверніть увагу, замість масиву з 8 змінних типу bool (8 байтів) ми використовуємо 1 змінну типу unsigned char (1 байт). Чому саме так? Про це читайте на уроці №48 і на уроці №49.

Тепер при оголошенні об’єкту класу Repository8<T>, де T не є bool, ми отримаємо екземпляр загального шаблону класу, тоді як при оголошенні об’єкту Repository8<bool>, ми отримаємо екземпляр шаблону Repository8<bool>. Зверніть увагу, ми не змінювали інтерфейс класу, а залишили його відкритим (яким він і був), в той час як мова C++ надає нам можливість додавати/змінювати/видаляти методи класу. Справа в тому, що зміна інтерфейсу класу в спеціалізаціях шаблону не завжди вітається, тому що програміст може про це забути, а воно, в свою чергу, призведе до помилок.

Створимо об’єкти Repository8<T> і Repository8<bool>:

Як ви можете бачити, результат той же, що і вище, де використовувався загальний шаблон класу Repository8:

0
1
2
3
4
5
6
7
false
true
true
true
true
false
true
true

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

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (2 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *