可以分为隐式类型转换和显示类型转换,显示类型转换也称为强制类型转换(cast),有四种名字命名的强制类型转换操作符:static_cast、dynamic_cast、const_cast、reinterpret_cast。
隐式的类型转换比较常见,在混合的类型表达式中经常发生。最简单的为整型提升,对于所有比int小的整型,包括char、signed char、unsigned char、short和unsigned short如果该类型的所有可能值都能包容在int内,它们就会被提升为int型,否则,将被提升为unsigned int。在包含short和int类型的表达式中,short转化为int,如果int类型足够表示所有的unsigned short类型,则unsigned short类型被转化为int,否则将转化为unsigned int。32位的机器上long和int通常用一个字长来表示,因此当表达式中包含unsigned int和两种类型,其操作数都应转换为unsigned long型。
static_cast
编译器隐式执行的任何类型转换都可以由static_cast显示完成。
#include <iostream>
using namespace std;
int main()
{
double d = 97.11;
char ch = static_cast<char>(d);
cout<<ch<<endl;
return 0;
}
输出为a(a的ascii码为97)。
const_cast
Primary上说:“这个操作符将转换掉表达式的const性质”,这句话感觉说的很有水平,但是又有点含糊不清。首先,必须明确的一点是,绝对不可以对cosnt常量重新赋值。有代码如下:
#include <iostream>
using namespace std;
int main()
{
const int a = 1;
const int *p = &a;
int *modify = const_cast<int *>(p);
//隐式转换形式为int *modify = (int *)p;
*modify = 2;
cout<<a<<endl;
cout<<*p<<endl;
cout<<*modify<<endl;
cout<<&a<<endl;
cout<<p<<endl;
cout<<modify<<endl;
return 0;
}
输出为
1
2
2
0xbff46978
0xbff46978
0xbff46978
结果有点出乎意料,但是非常明确的一点就是a这个const量是没有改变的。三个东西的地址又完全一样但结果不一样,这种行为标准C++是没有定义,为“未定义行为”,结果根据编译器不同而实现方式不同。(可能有的编译器它们的地址就不一样了)。感觉这时个没有的技巧,但是在一种情况下还是有用的,例如别人的接口函数,传入参数为non-const的(这个函数接口一般不修改这个参数,如果修改了,就会出现上面的未定义行为),而我们只有变量为const的值,这个时候这个技巧就可以用了。
dynamic_cast
首先有个概念RTTI(run-time tpye identification)运行时类型识别,程序能够使用基类的指针或引用来检索这些指针或引用所指对象的实际派生类型。通过typeid和dynamic_cast操作符来提供RTTI。对于带虚函数的类,在运行时执行RTTI,但对于其他类型,在编译时候计算RTTI操作符。
已经有虚函数了,从基类获得派生类行为的最好方法是通过虚函数,当使用虚函数的时候,编译器自动根据对象的实际类型选择正确的函数,为什么还要这两个操作符呢?Primary上“在某些情况下,不可能使用虚函数,在这些情况下,RTTI提供了可选择的机制”,至于某些情况是什么情况,我也不大清楚了。
dynamic_cast操作符将基类类型的指针或引用安全地转换为派生类型的指针或引用。与dynamic_cast一起使用的指针必须是有效的-它必须为0或者指向一个对象。如果转换到指针类型的dynamic_cast失败,则dynamic_cast的结果是0值;如果转换到引用类型的dynamic_cast失败,则抛出一个bad_cast类型的异常。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void show()
{printf("This is Base\n");}
};
class Derived:public Base
{
public:
void show()
{printf("This is Derived\n");}
void fun()
{printf("This is a Derived fun");}
};
int main()
{
Base *pBase;
Derived derived;
pBase = &derived;
pBase->show();
//pBase->fun(); 编译错误:‘class Base’ 没有名为 ‘fun’ 的成员
if(Derived *pDerived= dynamic_cast<Derived *>(pBase))
pDerived->fun(); //OK
return 0;
}
输出为:
This is Derived
This is a Derived fun
也可以将基类引用转换为派生类引用,dynamic_cast<Type &>(val)这里,Type是转换的目标类型。只有当val实际引用一个Type类型的对象,或者val是一个Type派生类型的对象的时候,dynamic_cast操作才将操作数val转换为想要的Type&类型。因为不存在空引用,所以不可能对引用使用用于指针强制类型转换的检查策略,当转换失败的时候,抛出一个bad_cast异常。
void f(const Base &b)
{
try{
const Derived &d = dynamic_cast<const Derived&>(b);
}catch (bad_cast){
//handle the cast failed
}
}
参考:
http://www.cnblogs.com/ider/archive/2011/07/22/cpp_cast_operator_part2.html
C++ primary