强制类型转换 (c++primer)

命名的强制类型转换符号的一般形式如下:

     cast-name<type>(expression);

其中 cast-namestatic_castdynamic_castconst_castreinterpret_cast 之一,type 为转换的目标类型,而 expression 则是被强制转换的值。强制转换的类型指定了在 expression 上执行某种特定类型的转换。

dynamic_cast

dynamic_cast 支持运行时识别指针或引用所指向的对象。

const_cast

const_cast ,顾名思义,将转换掉表达式的 const 性质。例如,假设有函数 string_copy,只有唯一的参数,为 char* 类型,我们对该函数只读不写。在访问该函数时,最好的选择是修改它让它接受 const char* 类型的参数。如果不行,可通过 const_cast 用一个 const 值调用 string_copy 函数:

     const char *pc_str;
     char *pc = string_copy(const_cast<char*>(pc_str));

只有使用 const_cast 才能将 const 性质转换掉。在这种情况下,试图使用其他三种形式的强制转换都会导致编译时的错误。类似地,除了添加或删除 const 特性,用 const_cast 符来执行其他任何类型转换,都会引起编译错误。

static_cast

编译器隐式执行的任何类型转换都可以由 static_cast 显式完成:

     double d = 97.0;
     // cast specified to indicate that the conversion is intentional
     char ch = static_cast<char>(d);

当需要将一个较大的算术类型赋值给较小的类型时,使用强制转换非常有用。此时,强制类型转换告诉程序的读者和编译器:我们知道并且不关心潜在的精度损失。对于从一个较大的算术类型到一个较小类型的赋值,编译器通常会产生警告。当我们显式地提供强制类型转换时,警告信息就会被关闭。

如果编译器不提供自动转换,使用 static_cast 来执行类型转换也是很有用的。例如,下面的程序使用 static_cast 找回存放在 void* 指针中的值(第 4.2.2 节):

     void* p = &d; // ok: address of any data object can be stored in a void*
     // ok: converts void* back to the original pointer type
     double *dp = static_cast<double*>(p);

可通过 static_cast 将存放在 void* 中的指针值强制转换为原来的指针类型,此时我们应确保保持指针值。也就是说,强制转换的结果应与原来的地址值相等。

reinterpret_cast

reinterpret_cast 通常为操作数的位模式提供较低层次的重新解释。

注意:

reinterpret_cast 本质上依赖于机器。为了安全地使用 reinterpret_cast,要求程序员完全理解所涉及的数据类型,以及编译器实现强制类型转换的细节。


建议:避免使用强制类型转换

强制类型转换关闭或挂起了正常的类型检查。强烈建议程序员避免使用强制类型转换,不依赖强制类型转换也能写出很好的 C++ 程序。

这个建议在如何看待 reinterpret_cast 的使用时非常重要。此类强制转换总是非常危险的。相似地,使用 const_cast 也总是预示着设计缺陷。设计合理的系统应不需要使用强制转换抛弃 const 特性。其他的强制转换,如 static_castdynamic_cast,各有各的用途,但都不应频繁使用。每次使用强制转换前,程序员应该仔细考虑是否还有其他不同的方法可以达到同一目的。如果非强制转换不可,则应限制强制转换值的作用域,并且记录所有假定涉及的类型,这样能减少错误发生的机会。

在引入命名的强制类型转换操作符之前,显式强制转换用圆括号将类型括起来实现:

     char *pc = (char*) ip;

旧式强制类型转换

在引入命名的强制类型转换操作符之前,显式强制转换用圆括号将类型括起来实现:

     char *pc = (char*) ip;

效果与使用 reinterpret_cast 符号相同,但这种强制转换的可视性比较差,难以跟踪错误的转换。

标准 C++ 为了加强类型转换的可视性,引入命名的强制转换操作符,为程序员在必须使用强制转换时提供了更好的工具。例如,非指针的 static_castconst_cast 要比 reinterpret_cast 更安全。结果使程序员(以及读者和操纵程序的工具)可清楚地辨别代码中每个显式的强制转换潜在的风险级别。

虽然标准 C++ 仍然支持旧式强制转换符号,但是我们建议,只有在 C 语言或标准 C++ 之前的编译器上编写代码时,才使用这种语法。

旧式强制转换符号有下列两种形式:

     type (expr); // Function-style cast notation
     (type) expr; // C-language-style cast notation

旧式强制转换依赖于所涉及的数据类型,具有与 const_caststatic_castreinterpret_cast 一样的行为。在合法使用 static_castconst_cast 的地方,旧式强制转换提供了与各自对应的命名强制转换一样的功能。如果这两种强制转换均不合法,则旧式强制转换执行 reinterpret_cast 功能。例如,我们可用旧式符号重写上一节的强制转换:

    int ival; double dval;
     ival += int (dval); // static_cast: converts double to int
     const char* pc_str;
     string_copy((char*)pc_str); // const_cast: casts away const
     int *ip;
     char *pc = (char*)ip; // reinterpret_cast: treats int* as char*

支持旧式强制转换符号是为了对“在标准 C++ 之前编写的程序”保持向后兼容性,并保持与 C 语言的兼容性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值