Приведение типов
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*
и обратно; его нужно использовать, только есть чёткое понимание что происходит
Источники: