一: 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使用