Урок 143. Конструкторы преобразования. Ключевые слова explicit и delete

  Юрий Ворон  | 

    | 

  Обновлено 11 мая 2018  | 

 1755

 ǀ   2 

По умолчанию 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. Результат — не то, что нужно (неожиданный).

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

Программа выше не скомпилируется, так как SomeString(int) мы сделали явным, а другого конструктора преобразования, который бы выполнил неявную конвертацию ‘a’ в SomeString компилятор просто не нашел.

Однако использование явного конструктора только предотвращает выполнение неявных преобразований. Явные конвертации (через операторы cast) по-прежнему разрешены:

Еще при прямой или uniform инициализации неявная конвертация также будет выполняться:

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

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

Еще одним способом запретить конвертацию ‘a’ в SomeString (неявным или явным способом) является добавление закрытого конструктора SomeString(char):

Тем не менее, этот конструктор все еще может использоваться внутри класса (private закрывает доступ к данным только для объектов вне класса).



Лучшее решение — использовать ключевое слово delete (добавленное в C++11) для удаления этого конструктора:

После удаления функции, любое её использование вызовет ошибку компиляции.

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

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (12 оценок, среднее: 4,92 из 5)
Загрузка...

Комментариев: 2

  1. Slava:

    Привет! Мне нравится визуальный стиль оформления твоего листинга. Не мог бы ты скинуть данные по этому стилю, хочу его в CodeBlock засунуть.

    1. Юрий Ворон Юрий Ворон:

      Привет. Тема Monokai. Вот ссылка на цвета — Monokai.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

ВОЛШЕБНАЯ ТАБЛЕТКА ПО С++