深入解析 C++ 类型转换
简介
C++ 类型转换是开发者必须掌握的重要技能之一, 无论是处理隐式转换还是显式转换, 理解其背后的机制与用法至关重要. 本篇博客旨在从基础到高级全面解析 C++ 的类型转换, 包括实际开发中的应用场景和性能分析.
自动转换
隐式类型转换
编译器可以在无需明确指示的情况下, 将一种类型的值自动转换为另一种兼容类型. 例如:
算术类型转换
符号转换
用户转换运算符
显示类型转换
C 风格类型转换
- 使用
var
创建<type>
的临时变量 <type>
可以是任何带有限定符的有效类型- 通过更改变量中位的含义来覆盖类型系统
- 在某些情况下无法编译(稍后详细介绍)
- 支持在
constexpr
上下文中使用(稍后详细介绍) - 可能导致未定义的行为
- 参与运算符优先级(级别 3)
C 风格和函数式符号转换的问题
- 单一符号, 多重含义
- 容易出错
- 无法
grep
- 使 C 和 C++ 语法复杂化
C++ 强制转换的目标
- 不同的符号或不同的任务
- 易于识别和搜索
- 执行 C 强制转换可以执行的所有操作
- 消除意外错误
- 使强制转换不那么诱人
C++有如下几种类型转换的关键词:
static_cast
const_cast
dynamic_cast
reinterpret_cast
static_cast
- 从
var
类型创建临时变量 - 尝试通过隐式和用户定义的转换或构造找到从
T1
到T2
的路径. 无法删除const
限定.
使用场景:
阐明隐式转换
指示有意截断
在基类和派生类之间进行强制转换
在
void*
和T*
之间进行强制转换
多重转换
A
有一个接受单个int
的构造函数E
有一个用户定义的到int
的转换- 所以从
e
到a
的路径为:e
->int
->a
static_cast 与继承
为什么会出现这样的情况? 因为Derived
的布局为:
static_cast 并非绝对正确
static_cast
无法防止向下转型为不相关的类型
const_cast
- 从变量中删除或添加
const
或volatile
限定符, 不能更改类型 - 不会更改原始变量的 CV 限定符
输出
可以看到虽然在函数modify_pointer
里面指针指向的值发生了变化, 但是在外面的值却不受影响.
const_cast example: member overload
用于防止成员函数的代码重复.
运行时类型信息 (RTTI)
- 为实现定义的结构中的每个多态类型存储额外信息
- 允许在运行时查询类型信息
- 可以禁用以节省空间(gcc/clang:
–fno-rtti
, msvc:/GR-
)
dynamic_cast
- 查看 To 是否与 From 位于同一公共继承树中
- 只能是引用或指针
- 不能删除 CV
- From 必须是多态的
- 需要 RTTI
- 如果类型不相关, 则对指针返回 nullptr, 对引用抛出
std::bad_cast
dynamic_cast 用例: UI 框架
dynamic_cast
can be expensive
from gcc’s rtti.c
reinterpret_cast
- 可以将任何指针或引用类型更改为任何其他指针或引用类型
- 也称为类型双关
- 不能在 constexpr 上下文中使用
- 不能删除 CV 限定
- 不确保 To 和 From 的大小相同
- 适用于内存映射功能
reinterpret_cast 访问私有继承的基类
Type Aliasing
当两种类型的内存布局兼容时, 将一种类型的内存当作另一种类型的内存来使用的行为.
compatible types
incompatible types
C 风格类型转换在 C++ 中是如何实际执行的
对与一个类型转换
C++会依次尝试:
T conv = const_cast<T>(val);
T conv = static_cast<T>(val);
T conv = const_cast<T>(static_cast<const T>(val));
T conv = reinterpret_cast<T>(val);
T conv = const_cast<T>(reinterpret_cast<const T>(val));
如果找到匹配则会选择并执行编译, 否则会报错.
总结
C++ 提供了更安全, 更明确的类型转换工具, 开发者应根据场景选择合适的转换方式. 通过熟练掌握这些工具, 您可以编写更健壮, 更易维护的代码. 希望本博客能帮助您更深入地理解 C++ 类型转换的精髓!
参考资源
Tags: