【C++】四种强制类型转化
1)static_cast
这应该四种中是最常见的。用法为 static_cast (expression)。
与C风格的强制类型转化相似, float b = 0.5; int a = b; 这样隐式截断(by the way 这样隐式的截断是向 0 取整的,我喜欢这么叫因为 0.9 会变成 0,1.9 变成 1,-0.9 变成 0,-1.9 变成 -1
主要用法区别在于:
用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
- 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
- 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,是不安全的。
2)const_cast
上边的 static_cast 不能将 const int* 转成 int*,const_cast 就可以
用法为 const_cast (expression)。如下面代码:
const int a = 10;
const int * p = &a;
// Compile error: Cannot assign readonly type 'int
*p = 20;
// Compile error: Cannot cast from 'int' to 'int' via const_cast
const int res1 = const_cast<int>(a);
// only conversions to reference or pointer types are allowed
int* res2 = const_cast<int*>(p); // ok
也就是说,const_cast<>里边的内容必须是引用或者指针,就连把 int 转成 int 都不行。
对于 const_cast 的使用
总结来说,const_cast 通常是无奈之举,只是 C++ 提供了一种修改 const 变量的方式,但这种方式并没有什么实质性的用处,还是不用的好。const 的变量不要让它变。
3)reinterpret_cast
reinterpret_cast 主要有三种强制转换用途:
1、改变指针或引用的类型
2、将指针或引用转换为一个足够长度的整形
3、将整型转换为指针或引用类型。
用法为 reinterpret_cast (expression)。
type-id 必须是一个指针、引用、算术类型、函数针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的。(这句话是C++编程思想中的原话)。因此, 你需要谨慎使用 reinterpret_cast。
4)dynamic_cast
用法为 dynamic_cast (expression)。
几个特点如下:
(1)其他三种都是编译时完成的,dynamic_cast 是运行时处理的,运行时要进行类型检查。
(2)不能用于内置的基本数据类型的强制转换
(3)dynamic_cast 要求 <> 内所描述的目标类型必须为指针或引用。dynamic_cast 转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回 nullptr
(4)在类的转换时:
- 在类层次间进行上行转换(子类指针指向父类指针)时:
dynamic_cast 和 static_cast 的效果是一样的。
- 在进行下行转换(父类指针转化为子类指针)时:
dynamic_cast 具有类型检查的功能,比 static_cast 更安全。 向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。在C++中,编译期的类型转换有可能会在运行时出现错误,特别是涉及到类对象的指针或引用操作时,更容易产生错误。Dynamic_cast操作符则可以在运行期对可能产生问题的类型转换进行测试。
(5)使用 dynamic_cast 进行转换的,基类中一定要有虚函数,否则编译不通过(类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义)。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表(C++中的虚函数基本原理这篇文章写得不错,