Перейти к основному содержимому

Приведение типов

C++ поддерживает 4 вида приведения типов: static_cast, dynamic_cast, const_cast, reinterpret_cast, а также приведение в стиле Си.

C-style cast

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

float x = 0.9;
std::cout << (int)x << std::endl; // 0
std::cout << (double)x << std::endl; // 0.9

Static cast

Применяется для неполиморфного приведения типов на этапе компиляции программы. Отличие static_cast от приведения в стиле Си состоит в том, что данный оператор может отслеживать недопустимые преобразования (будет выдана ошибка на этапе компиляции).

enum class Encoding { ASCII, UTF8, UTF16 };
std::cout << static_cast<int>(Encoding::UTF8); // 1

Const cast

Добавляет или удаляет атрибуты const и volatile (cv-qualifiers) у значения. Другие операторы приведения типов не влияют на эти атрибуты.

const std::string s = "const";
const_cast<std::string&>(s).insert(0, "no ");
std::cout << s; // "no const"

Не компилируется в какие-либо машинные инструкции.

Reinterpret cast

"Переосмысливает" тип; это директива времени компиляции, которая указывает компилятору обрабатывать выражение так, как если бы оно имело целевой тип.

Может делать небезопасное приведение типов через ссылки и указатели, но не напрямую по значению.

struct Point  { float x; float y; };
struct Vector { float x; float y; };

auto* p = new Point{1, 2};
auto* v = reinterpret_cast<Vector*>(p);

Не компилируется в какие-либо машинные инструкции.

Dynamic cast

Предназначен для приведения полиморфных типов по иерархии наследования (класс считается полиморфным, если в нем есть хотя бы одна виртуальная функция).

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

Если приведение невозможно, то на этапе выполнения программы будет возвращен nullptr, если приводятся указатели. Если приведение производится над ссылками, то будет сгенерировано исключение std::bad_cast.

Способность приводить полиморфные типы обеспечивается системой RTTI (Run-Time Type Identification), которая позволяет идентифицировать тип объекта в процессе выполнения программы.

Использование

  • для преобразований арифметических типов правильнее всего использовать инициализацию в фигурных скобках int{x}; код не будет компилироваться, если преобразование может привести к потере информации

  • static_cast обычно используется как эквивалент приведения в стиле Си

  • const_cast используется для снятия атрибута const или volatile

  • reinterpret_cast обычно используется для небезопасных преобразований типов указателей в целочисленные и другие типы указателей, включая void* и обратно; его нужно использовать, только есть чёткое понимание что происходит


Источники: