- C++有四种自带的转型操作
参考:C++ static_cast、dynamic_cast、const_cast和reinterpret_cast(四种类型转换运算符)、
- 语法格式:xxx_cast<newType>(data) 将data转换为newType,根据data的不同对应xxx_cast
- static_cast:static_cast 不能用于无关类型之间的转换,static_cast 是“静态转换”的意思,也就是在编译期间转换,转换失败的话会抛出一个编译错误。
//老式转换 double scores = 95.5; int n = (int)scores; //新的转换格式 double scores = 95.5; int n = static_cast<int>(scores);
- const_cast 比较好理解,它用来去掉表达式的 const 修饰或 volatile 修饰。换句话说,const_cast 就是用来将 const/volatile 类型转换为非 const/volatile 类型。
const int n = 100; int *p = const_cast<int*>(&n);
reinterpret_cast: reinterpret 是“重新解释”的意思,顾名思义,reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴,所以风险很高。和static_cast很象,都是强转的意思,因此都不太安全。
char str[]="http://c.biancheng.net"; float *p1 = reinterpret_cast<float*>(str); //把内存中的str[]按float的方式来解释吗可以转换,但不安全
dynamic_cast :dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。
class Base { public: virtual void foo() {} //必须含有虚函数,否则不能执行dynamic_cast }; class Derived :public Base {}; int main() { Base *bp = new Base; //成功返回Derived指针,失败返回0 if (Derived *dp = dynamic_cast<Derived*>(bp)) //局部dp保证了dp只能作用于if { ... } { //使用dp指向的Derived对象 } else { //使用bp指向的Base对象 } return 0; }
(1)向上转型(Derived类转Base类):都是允许的,因为继承,向上转型肯定是可以的。
(2)向下转型(Base类转Derived类):Derived *dp = dynamic_cast<Derived*>(bp);一看就是不安全的,将Base类转向Derived类,幸好dynamic_cast提供了检测机制,如果Derived *dp = dynamic_cast<Derived*>(bp)转换失败,dp是0
(3)对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用
(4)对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针
(5)只有真正的Derived对象才可以被向下转型,例如:
#include<iostream> using namespace std; class Base { //something public: // dynamic_cast只有在类有虚函数时才会进行类型检查,所以要使用dynamic_cast就需要定义虚函数 virtual void print() { cout<<"I'm Base!"<<endl;} }; class Sub: public Base { //something public: virtual void print() { cout<<"I'm Sub!"<<endl;} }; int main() { Sub sub2; // 基类到派生类的向下转换 // 此时,只有基类指针运行是真正指向继承类才能转换成功 Base base2; Sub* sub_ptr2=dynamic_cast<Sub*>(&base2); if(sub_ptr2!=NULL){ //此时转换失败 ,sub_ptr2是NULL sub_ptr2->print(); } cout<<"sub ptr2:"<<sub_ptr2<<endl; //输出: sub ptr2:0x0 Base* base3=&sub2; Sub* sub_ptr3=dynamic_cast<Sub*>(base3); if(sub_ptr3!=NULL){ sub_ptr3->print(); //输出: I'm Sub! } cout<<"sub ptr3:"<<sub_ptr3<<endl; //输出: sub ptr3:0x7ffee2665438 return 0; }