类型转换
本篇主要探讨C++11的新出现的类型转换方式
隐式类型转换(意义相近的类型可转换)
显示类型转换(意义不相近的类型需强制类型转换)
C++为了加强类型转换的可视性, 引入了四种命名强制类型转换操作符
但同时也兼容了C语言之前的类型转换和强制类型转换, 只是提供了规范的转换方式:
(T为要转换为什么类型, 变量即要进行转换的变量)
static_cast(变量)
用于执行非多态类型的转换,或意义相近的类型之间的转换,如整数和浮点数的转换, 如果类型不相近则会报错
tips:static_cast 不会进行运行时类型检查,因此在执行不安全的转换(如向下转型)时可能会导致未定义行为。
reinterpret_cast(变量)
reinterpret: 重新解释; 重新诠释
用于意义不相关之间的类型的转换,(如指针和长整型)
tips:reinterpret_cast 几乎不执行任何类型检查,因此它允许执行不安全的转换。使用 reinterpret_cast 时必须非常小心,因为它可能会破坏类型系统的安全性。
const_cast(变量)
用于去除对象的常量性或挥发性,或向对象添加常量性或挥发性。一般是同类型的const与非const之间转换
常用于去除转换变量的const属性
const int x = 10;
const int* p = &x; // 指向const int的指针 // 使用const_cast去除const属性
int* q = const_cast<int*>(p);
*q = 20; // 现在可以修改x的值(尽管这是不安全的) // 注意:尝试修改一个真正的const对象(如上面的x)会导致未定义行为
// 因为x是在一个只读的内存区域(如字符串常量区)中分配的
int y = 30;
int* r = &y; // 指向int的指针 // 使用const_cast添加const属性(虽然这通常是不必要的)
const int* s = const_cast<const int*>(r);
// 现在s是一个指向const int的指针,你不能通过s来修改y的值
// 但你仍然可以通过r来修改y的值
额外说明:
- const类型的变量较小时, 会加载到寄存器中提高访问速度, 读该变量时会从寄存器中读取
(vs下是直接将const变量定义成宏, 进行读时会直接将值代入) - 当对内存上的const变量通过某种方式间接修改时, 内存上改变了, 但读该变量时仍是寄存器内的数据
tips: 可以使用volatile关键字修饰const变量, 令编译器不进行优化, 直接取内存中的const变量值。
遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt;
当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。
dynamic_cast
用于将一个父类对象的指针/引用(原先需是指向或引用子类对象)转换为子类对象的指针/引用(动态转换), 即向下转型
- dynamic_cast只能用于父类含有虚函数的类(即必须是个多态类型)
- dynamic_cast会先检查是否能转换成功, 若能成功则转换, 不能成功则返回nullptr(故此使用dynamic_cast是安全的)
若原先父类指针指向子类对象则可成功转换, 若指向父类对象则会转换失败 - 向下转换后可以通过该父类指针或引用可访问子类中的成员
tips: 一个父类对象无论如何都无法转换为子类对象的, 能转换的只是指针或者引用
- RTTI(Run-time Type identification): 运行时类型识别
-
dynamic_cast运算符: 用于识别父类指针指向的是父类对象还是子类对象
-
decltype关键字: 用于获取类型 获取类型后可以再用该类型声明变量
如int x = 10; decltype(x) y1 = 20.22;
typeid(变量名): 用于获取变量类型的字符串
-