10.强制类型转换
强制类型转换
1 强制类型转换
C 强制类型转换
1 | (type-id)expression//转换格式1 |
- 强制类型转换。可能会丢失精度。
- 隐式类型转换。默认情况下会向上转换,即向位数更多的位置转换。
- 避免无符号和有符号的混用。带符号的数会自动转换成无符号的数。
C++强制类型转换
1 | static_cast<new_type> (expression) |
- static_cast
- dynamic_cast
- const_cast
- reinterpret_cast
2 详解
static_cast
static_cast 相当于传统的 C 语言里的强制转换,该运算符把 expression 转换为 new_type 类型,用来强迫隐式转换,例如 non-const 对象转为 const 对象,编译时检查,用于非多态的转换,可以转换指针及其他,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
- 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
- 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
- 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
- 用于基本数据类型之间的转换,如把 int 转换成 char,把 int 转换成 enum。这种转换的安全性也要开发人员来保证。
- 把空指针转换成目标类型的空指针。
- 把任何类型的表达式转换成 void 类型。
注意:static_cast 不能转换掉 expression 的 const、volatile、或者__unaligned 属性。
- 基本类型数据转换举例如下:
1 | char a = 'a'; |
- 类上行和下行转换:
1 | if(Derived *dp = static_cast<Derived *>(bp)){//下行转换是不安全的 |
dynamic_cast
- dynamic_cast 主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换(cross cast)。
- 在类层次间进行上行转换时,dynamic_cast 和 static_cast 的效果是一样的;
- 在进行下行转换时,dynamic_cast 具有类型检查的功能,比 static_cast 更安全。
- dynamic_cast 是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。
1 | dynamic_cast<type*>(e) |
- type 必须是一个类类型
- 在第一种形式中,type 必须是一个有效的指针
- 在第二种形式中,type 必须是一个左值
- 在第三种形式中,type 必须是一个右值。
- 在上面所有形式中,e 的类型必须符合以下三个条件中的任何一个:
- e 的类型是是目标类型 type 的公有派生类
- e 的类型是目标 type 的共有基类
- e 的类型就是目标 type 的的类型。
- 如果一条 dynamic_cast 语句的转换目标是指针类型并且失败了,则结果为 0。如果转换目标是引用类型并且失败了,则 dynamic_cast 运算符将抛出一个 std::bad_cast 异常(该异常定义在 typeinfo 标准库头文件中)。e 也可以是一个空指针,结果是所需类型的空指针。
- 指针类型.
举例,Base 为包含至少一个虚函数的基类,Derived 是 Base 的共有派生类,如果有一个指向 Base 的指针 bp,我们可以在运行时将它转换成指向 Derived 的指针,代码如下:
1 | if(Derived _dp = dynamic_cast<Derived _>(bp)){ |
值得注意的是,在上述代码中,if 语句中定义了 dp,这样做的好处是可以在一个操作中同时完成类型转换和条件检查两项任务。
- 引用类型
因为不存在所谓空引用,所以引用类型的 dynamic_cast 转换与指针类型不同,在引用转换失败时,会抛出 std::bad_cast 异常,该异常定义在头文件 typeinfo 中。
1 | void f(const Base &b){ |
const_cast
const_cast,用于修改类型的 const 或 volatile 属性。
该运算符用来修改类型的 const(唯一有此能力的 C++-style 转型操作符)或 volatile 属性。除了 const 或 volatile 修饰之外, new_type 和 expression 的类型是一样的。
- 常量指针被转化成非常量的指针,并且仍然指向原来的对象;
- 常量引用被转换成非常量的引用,并且仍然指向原来的对象;
- const_cast 一般用于修改底指针。如 const char *p 形式。
举例转换如下
1 | const int g = 20; |
reinterpret_cast
new_type 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。
reinterpret_cast 意图执行低级转型,实际动作(及结果)可能取决于编辑器,这也就表示它不可移植。
举一个错误使用 reintepret_cast 例子,将整数类型转换成函数指针后,vc++在执行过程中会报”…中的 0xxxxxxxxx 处有未经处理的异常: 0xC0000005: Access violation”错误:
1 | #include <iostream> |
3 c++强制转换注意事项
- 新式转换较旧式转换更受欢迎。原因有二,一是新式转型较易辨别,能简化“找出类型系统在哪个地方被破坏”的过程;二是各转型动作的目标愈窄化,编译器愈能诊断出错误的运用。
- 尽量少使用转型操作,尤其是 dynamic_cast,耗时较高,会导致性能的下降,尽量使用其他方法替代。








