除非必要,尽量不要对变量进行强制转换。这是因为强制转换是存在风险的,但实际上在某种情况下,转型是必需的。
旧式C转型方式为(type)expression,即由一对小括号加上一个对象名称组成,而这种语法结构在C++的任何地方都有可能使用,这就无法直观的判断出是否是转型操作。
在C++中,旧式的C转型方式并非是唯一的选择方式,我们有了新式的类型转换,与老式的C转换允许将任何类型转换为任何其他类型这种释放拙劣的行为相比,C++引入的新式的转换方式可精确地指明转换的意图。
1.static_cast
static_cast<type-id>(expression) 该运算符把expression转换为type-id类型,但没有运行时的类型检查来保证转换的安全性。
int fistNum,secondNum; int fistNum,secondNum;
double res = (double)firstNum/sencondNum; //旧式转换 double res = static_cast<double>(firstNum)/secondNum; //新式转换
static_cast用途比较广泛,编译器隐式执行的任何类型转换都可使用其来实现,几种用法如下
(1)用于类层次结构中基类和子类之间指针或引用的转换
(2)进行上行转换(把子类的指针或引用转换成基类表示)是安全的
(3)把空指针转换成目标类型的空指针
(4)把任何类型的表达式转换成void类型
(5)static_cast不能转换掉expression的const,volitale或_unaligned属性
(6)进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
(7)static_cast可用于将一个void*类型的指针强制转换为原来的指针类型,例如:
double d = 12;
void* p = &d;
double* pd = static_cast<double*>(p);
cout<<*pd<<endl; 输出结果12,说明转换后依然指向同一个地址。用于基本数据类型之间的转换。进行下行转换(把基类指针或引用转换成子类表示)
2.dynamic_cast
dynamic_cast<type-id>(expression) 该运算符把expression转换成type-id类型的对象。type-id必须是类的指针,类的引用或void*
如果type-id是类指针类型,那么expression也必须是一个指针
如果type-id是一个引用,那么expression也必须是一个引用
dynamic_cast要求派生类要有虚拟函数,否则编译不能通过
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
3.reinterpret_cast
reinterpret_cast<type-id>(expression)
type-id必须是一个指针,引用,算术类型,函数指针或者成员指针。例如:reinterpret_cast可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)
reinterpret_cast比static_cast更接近C的强制转换。它可以实现看起来没任何关系的两种类型的转换,当然它比static_cast危险
除非有必要,否则在C++编程中应尽量避免使用reinterpret_cast
static_cast在编译时使用类型信息执行转换,在转换执行必要的检测(诸如越界计算,类型检查)时,其操作数相对是安全的。reinterpret_cast仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换,例如:
int n = 9;
double d = static_cast<double>(n);
将一个变量从int转换到double,这种类型的二进制表达式是不同的。要将整数9转换到双精度整数9,static_cast需要正确地为双精度d补足比特位,其结果为9.0,而reinterpret_cast不会有这样的操作。
4.const_cast
const_cast<type-id>(expression) 主要用来修改类型的const或volatile属性,在使用过程中,除了const或volatile修饰之外,type-id和expression的类型是一样的。
尽管类型转换操作符的方式没有非常明显的优势,但还是建议在C++工程中尽量避免C风格的类型转换。使用类型转换操作符的方式进行类型转换,是一种好的编码习惯
由于强制类型转换无所不能,所以无形中会给C++程序带来很大的安全隐患。因此建议在C++代码中使用C++提供的除reinterpret_cast以外的3种转换方式。除非必要,否则应禁止使用强制类型转换和reinterpret_cast;