Урок №151. Конструктори конвертації, ключові слова explicit і delete

  Юрій  | 

  Оновл. 17 Лют 2021  | 

 93

За замовчуванням мова C++ обробляє будь-який конструктор, як оператор неявної конвертації. Розглянемо наступну програму:

Хоча функція makeNegative() очікує об’єкт класу Drob, ми передаємо їй цілочисельний літерал 7. Оскільки у класу Drob є конструктор, який може приймати одне цілочисельне значення (конструктор за замовчуванням), то компілятор виконає неявну конвертацію літералу 7 в об’єкт класу Drob. Це робиться шляхом виконання копіюючої ініціалізації параметру d функції makeNegative() за допомогою конструктора Drob(int, int).

Результат виконання програми:

Copy constructor worked here!
-7/1

Неявне перетворення працює для всіх видів ініціалізації (прямої, uniform- і копіюючої).

Конструктори, які використовуються в неявних конвертаціях, називаються конструкторами конвертації (або “конструкторами перетворення”). До C++11 конструкторами конвертації могли бути конструктори тільки з одним параметром. Однак в C++11 це обмеження було знято (разом з доданням uniform-ініціалізації), і конструктори, які мають кілька параметрів, вже також можуть бути конструкторами конвертації.

Ключове слово explicit

Іноді виконання неявних конвертацій може бути доречним, а іноді може бути вкрай небажаним і генерувати несподівані результати:

У прикладі, наведеному вище, ми намагаємося ініціалізувати рядок одним символом типу char. Оскільки змінні типу char є частиною сімейства цілочисельних типів, то компілятор використовуватиме конструктор конвертації SomeString(int) для неявного перетворення символу типу char в тип SomeString. В результаті змінна типу char конвертується в тип int. А це не зовсім те, що очікується.

Один із способів вирішення цієї проблеми — зробити конструктор явним, використовуючи ключове слово explicit (яке пишеться перед ім’ям конструктора). Явні конструктори (з ключовим словом explicit) не використовуються для неявних конвертацій:

Вищенаведена програма не скомпілюється, так як SomeString(int) ми зробили явним, а іншого конструктора конвертації, який виконав би неявну конвертацію 'a' в SomeString, компілятор просто не знайшов.

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

При прямій або uniform-ініціалізації неявна конвертація також виконуватиметься:

Правило: Для запобігання виникненню помилок з неявними конвертаціями робіть ваші конструктори явними, використовуючи ключове слово explicit.

Ключове слово delete

Ще одним способом заборонити конвертацію 'a' в SomeString (неявним або явним способом) є додання закритого конструктора SomeString(char):

Тим не менш, цей конструктор все ще може використовуватися всередині класу (private закриває доступ до даних тільки для об’єктів поза тілом класу).

Краще рішення — використовувати ключове слово delete (додане в C++11) для видалення цього конструктора:

Після видалення функції, будь-яке її використання викличе помилку компіляції.

Зверніть увагу, конструктор копіювання і перевантажені оператори також можуть бути видалені за допомогою delete для запобігання їх використанню.

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

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (Немає Оцінок)
Loading...

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

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