一: static_cast的使用
static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。static_cast主要有以下几种用法:
1. 用于类层次结构中基类和子类之间指针或引用的转换,通常进行上行转换是安全的;而进行下行转换时,由于没有动态类型检查,所以是不安全的。static_cast<Derived *>(base)
2. 用于内置基本数据类型之间的转换,如将int转换成double,int转换成enum。而这种转化也是不安全的。 static_cast<double>(int)
3. 将空指针转换成目标类型的空指针。 static_cast<int*>(void*)
4. 将任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volitale、或者__unaligned前缀修饰符
需要注意的是:
static_cast 和reinterpret_cast 在类继承层次间可以完成向下类型强制转化,但是dynamic_cast需要运行时(动态)的完成类型检查
二: dynamic_cast的使用
dynamic_cast < type-id > ( expression ) 该运算符将expression转换成type-id类型的对象。type-id必须是类的指针、类的引用或者void *;但记住就是不能为对象本身,要用对象本身可用static_cast<B>(b).
如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。
记住使用dynamic_cast转化中基类必须至少要有一个虚方法,记住哟
dynamic_cast是类层次间相关的(也即是类之间有继承关系),他会在运行时检查底层对象的运行时信息,对于类指针,如果类型强制转化没有意义,则会返回NULL,而对于
引用则会抛出std::bad_cast异常
比如:
class conV
{
public:
int n_M;
virtual void fun()
{
cout<<"virtual void fun()"<<endl;
}
};
class convv
{
public:
void fun();
};
void main()
{
conV *v;
conV rv;
conV &rf=rv;
try{
dynamic_cast<convv&>(rf);//这里很特别rf引用必须是多态类型,也就是说conV类中要有virtual方法呵,不信你去掉 virtual void fun()中的virtual
}catch(std::bad_cast)
{
cout<<"std::bad_cast"<<endl;
exit(0);
}
}
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
class B{
public:
int m_iNum;
virtual void foo();
};
class D:public B{
public:
char *m_szName[100];
};
void func(B *pb){
D *pd1 = static_cast<D *>(pb);
D *pd2 = dynamic_cast<D *>(pb);
}
在上面的代码段中,如果pb指向一个D类型的对象,pd1和pd2是一样的,并且对这两个指针执行D类型的任何操作都是安全的;
但是,如果pb指向的是一个B类型的对象,那么pd1将是一个指向该对象的指针,对它进行D类型的操作将是不安全的(如访问m_szName),而pd2将是一个空指针。
另外要注意:B要有虚函数,否则会编译出错;static_cast则没有这个限制。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见<Inside c++ object model>)中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。
另外,dynamic_cast还支持交叉转换(cross cast)。如下代码所示。
class A{
public:
int m_iNum;
virtual void f(){}
};
class B:public A{
};
class D:public A{
};
void foo(){
B *pb = new B;
pb->m_iNum = 100;
D *pd1 = static_cast<D *>(pb); //compile error
D *pd2 = dynamic_cast<D *>(pb); //pd2 is NULL
delete pb;
}
在函数foo中,使用static_cast进行转换是不被允许的,将在编译时出错;而使用 dynamic_cast的转换则是允许的,结果是空指针。
三: reinterpret_cast使用
reinterpret_cast< type-id > ( expression )是C++里的强制类型转换符。
reinterpret_cast是比static_cast更强大的功能,static_cast不能支持从int和指针的相互转化,也不支持从类层次(继承关系)上不相关的转化,但支持类层次相关的转化。如从一个对象或对象引用转化到另一个对象和对象引用,他们是不相关的。几乎所有的c++无意义的转化static_cast都不支持,但是reinterpret_cast可以,可以完成上面说的那些情况,但是随之带来的是安全性更低。
操作符修改了操作数类型,但仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换。
例如:int *n= new int ;
double *d=reinterpret_cast<double*> (n);
在进行计算以后, d 包含无用值. 这是因为 reinterpret_cast 仅仅是复制 n 的比特位到 d, 没有进行必要的分析。因此, 需要谨慎使用 reinterpret_cast. 并且:reinterpret_cast 只能在指针之间转换。
四: const_cast使用
int i;
float f = 166.7f;
i = static_cast<int>(f);
此时结果,i的值为166。
2、C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。比如:
int i;
char *p = "This is a example.";
i = reinterpret_cast<int>(p);
此时结果,i与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,并赋给i,一个明显的现象是在转换前后没有数位损失。
类型强制转化总结:记住有一点就是static_cast必须是类层次相关的,而reinterpret_cast可以也可不是类层次相关
转化情况 转化方法
删除常量型 const_cast
语言支持的显示类型转化如int和double间转化 static_cast
一种对象转化到另一种对象,即使类层次间相关 (就是有继承关系) 无法完成reinterpret_cast<Object2>(Object1);//报错
一种对象转化到另一种对象引用,即使类层次间不相关 可以完成reinterpret_cast<Object2&>(Object1);但是用static_cast<Object2&> (Object1);必须是类层次相关,否则报错
类层次间相关 ,一种对象指针 转化到另一种对象指针 reinterpret_cast<Object2*>(Object1); static_cast<Object2*>(Object1);dynamic_cast<Object2*>(Object1)都可
类层次间相关 ,一种对象引用 转化到另一种对象引用 reinterpret_cast<Object2&>(Object1); static_cast<Object2&>(Object1);dynamic_cast<Object2&>(Object1)三种都可
指针和int型之间的转化,注意不是和float或double reinterpret_cast
函数指针的转化 reinterpret_cast