四种cast转换

c++动态类型转换有四种const_cast、static_cast、dynamic_cast、reinterpreter_cast
前面两个用的多,但是后面的针对其设计理念有许多其他的实现方法可达到同样的效果

1、const_cast

用于将const变量转为非const

2、static_cast

用于各种隐式转换,比如非const转const,void*转指针等, static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知;

3、dynamic_cast

用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常。要深入了解内部转换的原理。

向上转换:指的是子类向基类的转换

向下转换:指的是基类向子类的转换

它通过判断在执行到该语句的时候变量的运行时类型和要转换的类型是否相同来判断是否能够进行向下转换。

4、reinterpret_cast

几乎什么都可以转,比如将int转指针,可能会出问题,尽量少用;

5、为什么不使用C的强制转换?

C的强制转换表面上看起来功能强大什么都能转,但是转化不够明确,不能进行错误检查,容易出错。


1. static_cast 


(1)用于基本数据类型之间的转换,如把int转换为char,把int转换成enum,但这种转换的安全性需要开发者自己保证(这可以理解为保证数据的精度,即程序员能不能保证自己想要的程序安全),如在把int转换为char时,如果char没有足够的比特位来存放int的值(int>127或int<-127时),那么static_cast所做的只是简单的截断,及简单地把int的低8位复制到char的8位中,并直接抛弃高位。 
(2)把空指针转换成目标类型的空指针 
(3)把任何类型的表达式类型转换成void类型 
(4)用于类层次结构中父类和子类之间指针和引用的转换。 
对于以上第(4)点,存在两种形式的转换,即上行转换(子类到父类)和下行转换(父类到子类)。对于static_cast,上行转换时安全的,而下行转换时不安全的,为什么呢?因为static_cast的转换是粗暴的,它仅根据类型转换语句中提供的信息(尖括号中的类型)来进行转换,这种转换方式对于上行转换,由于子类总是包含父类的所有数据成员和函数成员,因此从子类转换到父类的指针对象可以没有任何顾虑的访问其(指父类)的成员。而对于下行转换为什么不安全,是因为static_cast只是在编译时进行类型坚持,没有运行时的类型检查。

一般时候static_cast用的比较多,且与const_cast结合使用可以在父子类间完成常量属性与非常量属性的相关转换 
类似这样的: 

const_cast

class Widget{
public:
    virtual ~Widget(){};
};

class SpecialWidget:public Widget{
};
void update(SpecialWidget *psw){};
int main()
{
Widget *pw1=new SpecialWidget();//编译运行正常
Widget *pw2=new Widget();//编译运行正常
Widget *pw;  //编译正常,运行异常
update(dynamic_cast<SpecialWidget*>(pw));
return 0;
}


static_cast的一些用法及变形
 

​
class Base1{
virtual void f(){}
};
class Base2{};
class Derived:public Base1,public Base2{};
int main(int argc, char* argv[])
{
Derived d,*pd;
Base1 *b1=&d;

//用法一
if((pd=dynamic_cast<Derived*>(b1))!=0){
    cout<<"pd结果指针类型为:"<<typeid(pd).name()<<endl;
}

//用法二
Base2 *b2;
if((b2=dynamic_cast<Base2*>(b1))!=0){
    cout<<"b2结果指针类型为:"<<typeid(b2).name()<<endl;
}

​


结果如下:

pd结果指针类型为:P7Derived
b2结果指针类型为:P5Base2


3. const_cast 
const_cast目前基本只用在const的转换上,基本无其他用法,比较单一

4. reinterpret_cast 
reinterpret_cast的常用地方是转换”函数指针”类型。 
如下:

typedef void (*FuncPtr)(); //定义一个无参数且无返回值的函数指针
FuncPtr funcPtrArray[10];  //定义一个长度为10的数组,数组元素是函数指针类型
int doSomething(){  return 1;};//定义一个无参返回值为int的函数
int main()
{
//funcPtrArray[0]=&doSomething;  错误,函数类型不相符
funcPtrArray[0]=reinterpret_cast<FuncPtr>(&doSomething);//函数名就是一个地址,因此取地址符是可选的

但reinterpret_cast与编译器平台相关,因此不具有移植性,使用范围也有限。 
另外,倘若你用过的编译器版本比较老,不支持上面这些新用法,其实还可以用宏定义来实现强制类型转换的功能。
 

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值