Перейти к содержанию

Преобразования типов и приведение

Начало урока

Преобразования типов и приведение

Превращаем один тип в другой - безопасно, осознанно и только тогда, когда действительно этого хотим

Главная мысль: C++ - язык со строгой типизацией, но реальные программы постоянно переносят значения между типами: int в double, указатель на базовый класс в указатель на производный, дескриптор API в целое число. Часть этих преобразований происходит незаметно (компилятор вставляет их за вас), а часть вы обязаны запросить явно с помощью приведения. Понимание того, какие преобразования компилятор делает у вас за спиной, а какое из четырёх именованных приведений выбрать, когда вы берёте управление на себя, - это разница между кодом, корректность которого доказуема, и кодом, который тихо портит данные.
К концу урока вы сможете:
  • распознавать неявные преобразования и замечать опасное сужение,
  • использовать ключевое слово explicit, чтобы запретить нежелательные преобразования,
  • правильно выбирать между static_cast, dynamic_cast, const_cast и reinterpret_cast,
  • объяснять, почему в современном C++ не рекомендуется старое приведение в стиле C (T)x.

1. Неявные преобразования и сужение

Неявное преобразование - это преобразование, которое компилятор выполняет автоматически, без написанного вами приведения. Многие из них безобидны и полезны: присваивание int переменной типа double или передача char туда, где ожидается int. Это продвижения или расширяющие преобразования - тип-приёмник способен представить любое значение исходного типа, поэтому ничего не теряется.

Опасность - в обратном направлении: сужающее преобразование, когда тип-приёмник не может хранить каждое значение исходного типа. Присваивание double переменной int отбрасывает дробную часть; присваивание большого int переменной short может привести к переполнению и бессмысленному значению. Компилятор обычно молча это разрешает и в лучшем случае выдаёт предупреждение.

double pi = 3.14159;
int    n  = pi;        // сужение: n становится 3, часть .14159 теряется
long   big = 100000;
short  s  = big;       // сужение: возможно переполнение, значение зависит от реализации

Современный C++ даёт вам страховку: инициализация в фигурных скобках {} превращает сужающее преобразование в ошибку компиляции, а не в тихий сюрприз. Это одна из лучших причин предпочитать фигурные скобки для инициализации.

int a = 3.9;     // компилируется: a равно 3 (тихое сужение)
int b{3.9};      // ОШИБКА: сужающее преобразование внутри { } запрещено

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

Продолжите этот урок на YourAIZone

В полном уроке — объяснение целиком, разобранные примеры, частые ошибки, тесты с мгновенной проверкой и ИИ-репетитор. Начните сразу как гость или создайте аккаунт, чтобы сохранять прогресс.

В полном уроке

  • Объяснение целиком
  • Разобранные примеры
  • Частые ошибки и как их избежать
  • Тестовые вопросы: 15
  • ИИ-репетитор, который отвечает на вопросы по теме
  • Отслеживание прогресса для ученика, родителей и учителя