C++类型转换
隐试类型转换:
char c = 'A'; int x = c; //隐试类型转换 cout << x << endl;
显式类型转换:
//强制类型转换 char c = 'A'; int x = (int)c; //C风格 int y = int(c);//C++风格
C++扩展了四种操作符形式的转换:
static_cast:
static_cast相当于传统的C语言里的强制转换,该运算符把expression转换为new_type类型,用来强迫隐式转换
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
points.at<float>(index, 0) = static_cast<int>(bgr[0]); //把int转换成float
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性
//1.静态类型转换:static_cast //语法:目标变量=static_cast<目标类型>(源类型变量); //适用场景:将void*指针转化为其它类型的指针 int* pi = NULL; char c = long(pi); //强制类型转换这种不合理的转换可以通过 //char c2= static_cast<long>(pi); //不合理的转换会报错--编译器会自动检查是否合理 void* pv=pi; //pi = pv; 错误 //void*不能隐试转换成其它类型的指针 pi = static_cast<int*>(pv);//将void*转化为其它类型的指针
一个方向可以隐试转换,另一个方向就可以静态转换
dynamic_cast
#include<iostream> //2.动态类型转换:dynamic_cast //语法:目标变量=dynamic_cast<目标类型>(源类型变量); //主要用于具有多态特性父子类指针或引用之间的显示类型转换 class A { virtual void func() {} }; class B :public A { void func() {} }; class C :public A { void func() {} }; int main() { B b; A* pa = &b; //B* pb = pa; 报错 向下造型直接转是不允许的 //B* pb = static_cast<B*>(pa); //合理转换 //std::cout << "pa=" << pa << std::endl; //std::cout << "pb=" << pb << std::endl; //C* pc= static_cast<C*>(pa); //不合理--不报错 //原因:指针指向的目标对象不一致 //可是编译器认为从语法角度是合理的,编译成功,存在危险 B* pb = dynamic_cast<B*>(pa); //动态转换 C* pc = dynamic_cast<C*>(pa); //动态转换--不合理转换失败,返回NULL //不报错 //会自动检查是否合理 std::cout << "pa=" << pa << std::endl; std::cout << "pb=" << pb << std::endl; std::cout << "pc=" << pc << std::endl; if (pc == NULL) { std::cout << "转换失败"<< std::endl; } A& ra = b; //C& rc= dynamic_cast<C&>(ra); //不合理的引用转换--抛出异常 return 0; }
//3.去常类型转换:const_cast //语法:目标变量=const_cast<目标类型>(源类型变量); //目标类型 必须是指针 //适用场景:主要用于去掉指针或引用的const属性 volatile const int i = 100; //int* pi = &i; 错误,因为i是const,相当于常量,不能保存常量地址 int* pi = const_cast<int*>(&i); //通过const_cast的转换,去掉变量i的const属性后再赋值 //注意:变量i还是有const属性 *pi = 200; std::cout << "*pi=" << *pi << "," << "i=" << i << std::endl; /* 特殊注意: const的变量值第一次读取后会放到寄存区里,以后都从寄存器里读取,这样执行效率高 volatile的作用:使用该变量时,每次都从内存读取,而不是读取寄存器中的副本,这样保存const_cast转换后*pi的值和i的值相同 如果没有volatile,由于i是const,它就从寄存器读取值100 */ std::cout << "pi=" << pi << "," << "&i=" << (int*)&i << std::endl; //&i=1 是编译器的错,把它转换成布尔类型了,强制类型转换一下就OK了
//4.重解释类型转换:reinterpret_cast //语法:目标变量=reinterpret_cast<目标类型>(源类型变量); //适用场景一:指针和整型数之间进行转换 //int* p = 0x12345678; 错 int* p= reinterpret_cast<int*>(0x12345678);//把整形数转换成地址 //适用场景二:任意类型指针或引用之间转换 char buf[] = "0001\00012345678\000123456"; //"\000"-->'\0' struct A { char type[5]; char id[9]; char passwd[7]; }; A* a= reinterpret_cast<A*>(buf);//把数组变量转换成指针 cout << a->type << endl; cout << a->id << endl; cout << a->passwd << endl;