1. 显式转换
显式转换也称为强制类型转换(cast),包括如下列名字命名的强制类型转换操做符:
static_cast、dynamic_cast、const_cast、reinterpret_cast。
虽然有时候确实须要强制类型转换,可是它们本质上是很是危险的。
2. 什么时候须要强制类型转换
由于要覆盖一般的标准转换,因此需显式使用强制类型转换。下面的复合赋值:
double dval;
int ival;
ival = ival * dval;
为了与dval作乘法操做,需将ival转换为double型,而后将乘法操做的double型结果截尾为int型,再同赋值给ival。为了去掉将ival转换为dobule型这个没必要要的转换,可经过以下操做强制将dval转换为
int型:
ival *= static_cast<int>(dval); // converts dval to int
显式使用强制类型转换的另外一个缘由是:可能存在多种转换时,须要选择一种特定的类型转换。程序员
3. 命名的强制类型转换
命名的强制类型转换符号的通常形式以下:
cast-name<type>(expression);
其中cast-name为static_cast、dynamic_cast、const_cast和reinterpret_cast之一,type为转换的目标类型,而expression则是被强制转换的值。强制转换的类型指定了在expression上执行某种特定类型的转换。
dynamic_cast
dynamic_cast支持运行时识别指针或引用所指向的对象。如将基类对象转换为子类对象。express
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_csat找回存放在
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,要求程序员彻底理解所涉及的数据类型,以及编译器实现强制类型转换的细节。
例如,对于下面的强制转换:
int *ip;
char *pc = reinterpret_cast<char*>(ip);
程序员必须永远记得 pc 所指向的真实对象实际上是 int 型,而并不是字符数组。任何假设 pc 是普通字符指针的应用,都有可能带来有趣的运行时错误。例如,下面语句用 pc 来初始化一个 string 对象:
string str(pc);
它可能会引发运行时的怪异行为。
用 pc 初始化 str 这个例子很好地说明了显式强制转换是多么的危险。问题源于类型已经改变时编译器没有提供任何警告或错误提示。当咱们用 int 型地址初始化 pc 时,因为显式地声明了这样的转换是正确的,所以编译器不提供任何错误或警告信息。后面对 pc 的使用都假设它存放的是 char* 型对象的地址,编译器确实没法知道 pc 其实是指向 int 型对象的指针。所以用 pc 初始化 str是彻底正确的——虽然其实是无心义的或是错误的。查找这类问题的缘由至关困难,特别是若是 ip 到 pc 的强制转换和使用 pc 初始化 string对象这两个应用发生在不一样文件中的时候。
4. 避免使用强制类型转换
强制类型转换关闭或挂起了正常的类型检查。强烈建议程序员避免使用强制类型转换,不依赖强制类型转换也能写出很好的 C++程序。
这个建议在如何看待 reinterpret_cast 的使用时很是重要。此类强制转换老是很是危险的。类似地,使用 const_cast 也老是预示着设计缺陷。设计合理的系统应不须要使用强制转换抛弃 const 特性。其余的强制转换,如 static_cast 和 dynamic_cast,各有各的用途,但都不该频繁使用。每次使用强制转换前,程序员应该仔细考虑是否还有其余不一样的方法能够达到同一目的。若是非强制转换不可,则应限制强制转换值的做用域,而且记录全部假定涉及的类型,这样能减小错误发生的机会。
数组