在c语言中学的强制转换是用()
来实现的; 而在c++中更多的是用case-name
系列的关键字来告诉编译器咱们须要转换的类型. c++引入这些关键字也是为了看代码的时候清晰明了, 每一个关键字都有指定的功能. 下面咱们就来分析这些关键字.c++
在编译期间完成类型转换.安全
a. 将原有的自动类型转换 , 如 : short转为int, int转为double, 非const转为const类型函数
short sh; int i = static_cast<int>(sh); const int ci = static_cast<const int>(i);
b. void 指针和具体类型指针之间的转换 this
void *vp; int *ip = static_cast<int*>(vp);
c. 有转换构造函数或者类型转换函数的类与其它类型之间的转换指针
如 : A是B的基类code
B *b; A *a = static_cast<A *>(b); // 这种建议使用dynamic_cast来转换
不能用于无关类型之间的转换 , 如 : int* 转为double* 等对象
int *pi; double *di = static_cast<double *>(pi); // error
const_cast
(经常使用于函数的重载) 常量指针(引用)被转化成很是量指针(引用),而且仍然指向原来的对象继承
顾名思义, const_cast
就是在咱们须要修改const
修饰的常量的时候用.ip
const int ci = 1; int *p = const_cast<int*>(&ci); *p = 10; cout << &ci << " " << p << endl; // 0x7ffd856729cc 0x7ffd856729cc cout << ci << endl; // 1 cout << *p << endl; // 10
注意 : 上面的ci的值最终仍是没有被修改, 这就是后半句 : 仍然指向原来的对象. 咱们只能经过const_cast
忽略对象的属性, 却依然不能修改对象.ci
可能有人就认为const_cast
并无用, 可是咱们确实用int*
指向了const int*
了, 这是通常咱们都没法作到的. 一样, 下面还有const_cast
可以作到的.
这有一部分的代码, 咱们在重载const函数时, 经常会重复写不少同样的代码, 而使用const_cast
就能够避免写重复的代码.
class A { public: ... const type& operator[](std::size_t size) const { return *(ar + size); } type& operator[](std::size_t size) { return const_cast<type &>(static_cast<const A&>(*this)[size]); } private: ... std::size_t size; type * ar; };
reinterpret_cast
这种转换仅仅是对二进制位的从新解释(修改), 不会借助已有的转换规则对数据进行调整, 很是简单粗暴, 风险很高, 通常咱们不推荐使用.
可是既然c++规定了这中转换, 那么何时用合适?在IBM C++指南中明确说了
- 从指针类型到一个足够大的整数类型
- 从整数类型或者枚举类型到指针类型
- 从一个指向函数的指针到另外一个不一样类型的指向函数的指针
- 从一个指向对象的指针到另外一个不一样类型的指向对象的指针
- 从一个指向类函数成员的指针到另外一个指向不一样类型的函数成员的指针
- 从一个指向类数据成员的指针到另外一个指向不一样类型的数据成员的指针
总结来讲:reinterpret_cast用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。
就像下面这样static_cast
没法作的但reinterpret_cast
就能够完成, 可是赋值等操做却会运行时报错, 这就是reinterpret_cast
不安全之处, 它能让代码经过编译, 操做时却会报错, 通常建议reinterpret_cast
只有将转换后的类型值转换回到其原始类型来使用, 作一个中间临时转存。
int *pi = NULL; double *di = reinterpret_cast<double *>(pi);
dynamic_cast
用于在类的继承层次之间进行类型转换, 它既容许向上转型, 也容许向下转型.
class A {}; class B : public A {};
向上转型 : 基类指针(引用)指向子类指针(引用), 这样的转换是安全的.
B *b; A *a = static_cast<A *>(b); A *ta = dynamic_cast<A *>(b);// 也可写成这样, 最好建议这样转换
向下转型 : 借助 RTTI 信息进行检测, 肯定安全的才能转换成功, 不然就转换失败, 有风险.
A *a; B *b = dynamic_cast<B *>(a);
虽然c语言的()
强制能用, 可是最好推荐使用c++的转化系列, 毕竟看代码的时候很容易可以知道转化对象和缘由, 也容易分析. 本片我将四种转化尽可能写的简单, 多用实例证实, 只是但愿可以快速的明了每一个的用法.
static_cast
: 有关联的 对象之间可以进行转化.const_cast
: 忽略const/volatile修饰, 可是实际不会修改对象, 经常使用于重载dynamic_cast
: 最多用于向下转化, 但并不安全reinterpret_cast
: 二进制间, 可无关联对象间的转化, 很是不安全.