在C语言中,类型转换是这样子的
1 | void Test () |
但是这样的转换有很大的缺陷:
- 转换的可视性非常差,所以的转换形式都是同一种方式书写的,很难去跟踪错误的转换
- 转换太过随意,可以在任意类型之间转换。你可以把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成一个派生类对象的指针,这些转换之间的差距是非常巨大的,但是传统的C语言风格的类型转换没有区分这些
- C风格的转换没有统一的关键字和标示符。对于大型系统,做代码排查时容易遗漏和忽略。
而标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:static_cast,reinterpret_cast,const_cast,dynamic_cast。
一、static_cast
1.基本用法:static_cast
2.使用场景:
a、用于类层次结构中基类和派生类之间指针或引用的转换
上行转换(派生类—->基类)是安全的;
下行转换(基类—->派生类)由于没有动态类型检查,所以是不安全的。
b、用于基本数据类型之间的转换,如把int转换为char,这种带来安全性问题由程序员来保证
c、把空指针转换成目标类型的空指针
d、把任何类型的表达式转为void类型
3.使用特点
a、主要执行非多态的转换操作,用于代替C中通常的转换操作
b、隐式转换都建议使用static_cast进行标明和替换
1 | int main() |
二、reinterpret_cast
1.基本用法:reinterpret_cast
2.使用场景:用于将一种类型转换为另一种不同的类型(不到万不得已,不用使用这个转换符,高危操作)
3.使用特点:
a、reinterpret_cast是从底层对数据进行重新解释,依赖具体的平台,可移植性差
b、reinterpret_cast可以将整型转换为指针,也可以把指针转换为数组
c、reinterpret_cast可以在指针和引用里进行肆无忌惮的转换
1 | typedef void (* FUNC)(); |
三、const_cast
1.基本用法:const_cast
2.使用场景:
a、常量指针转换为非常量指针,并且仍然指向原来的对象
b、常量引用被转换为非常量引用,并且仍然指向原来的对象
3.使用特点:
a、cosnt_cast是四种类型转换符中唯一可以对常量进行操作的转换符
b、去除常量性是一个危险的动作,尽量避免使用。一个特定的场景是:类通过const提供重载时,一般都是非常量函数调用const_cast
1 | void Test () |
四、dynamic_cast
1.基本用法:dynamic_cast
2.使用场景:只有在派生类之间转换时才使用dynamic_cast,type-id必须是类指针,类引用或者void*。
3.使用特点:
a、基类必须要有虚函数,因为dynamic_cast是运行时类型检查,需要运行时类型信息,而这个信息是存储在类的虚函数表中,只有一个类定义了虚函数,才会有虚函数表(如果一个类没有虚函数,那么一般意义上,这个类的设计者也不想它成为一个基类)。
b、对于下行转换,dynamic_cast是安全的(当类型不一致时,转换过来的是空指针),而static_cast是不安全的(当类型不一致时,转换过来的是错误意义的指针,可能造成踩内存,非法访问等各种问题)
c、dynamic_cast还可以进行交叉转换
向上转型:子类对象指针->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针->子类指针/引用(用dynamic_cast转型是安全的)
1 | class A |
五、explicit关键字
explicit关键字阻止经过转换构造函数进行的隐式转换的发生
1 | class A |