深入理解C++(一)类型转换(Type Casting)_第1页
深入理解C++(一)类型转换(Type Casting)_第2页
深入理解C++(一)类型转换(Type Casting)_第3页
深入理解C++(一)类型转换(Type Casting)_第4页
深入理解C++(一)类型转换(Type Casting)_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

[深入理解C++(一)]类型转换(TypeCasting)分类:C/C++2012-10-2821:30394人阅读评论(2)收藏举报[深入理解C++(一)]类型转换(TypeCasting)

罗朝辉(/kesalin)CC许可,转载请注明出处

类型转换就是将给定类型的表达式转换为另一种类型。C++中的转型可分为两种:隐式类型转换和显式类型转换。下面将一一介绍。

一,隐式类型转换隐式类型转换是C中的遗留物,在C++中并不推荐使用(C++有专门的转型操作符,见下文的显式转型)。将某种类型的对象拷贝到另一种不同类型的对象中时就会发生隐式转型。比如异型赋值,返回值(函数声明的返回值与代码块实际返回值不同的情况下),按值传递异型参数等情况均会发生隐式类型转换。shorta=128;intb;b=a;

如上所示,short类型的对象被赋值给int型的对象,这是C++语言内建支持的标准转换。情形一:标准转换支持数值类型,bool以及某些指针之间相互转换。注意:某些转换可能会导致精度丢失,比如从long转换到int。情形二:可被单参调用(只有一个参数或多个参数但至少从第二个参数起均带有缺省值)的构造函数或隐式类型转换操作符也会引起隐式类型转换。比如:classA{};classB{public:B(Aa){}public:B(intc,intd=0);public:operatordouble()const;};Aa;Bb1=a;Bb2=10;Bb3;doubled;d=10+b3;上面的代码里就存在只带有一个参数的构造函数,多个参数但至少从第二个参数起均带有缺省值以及用户自定义类型转换操作符这三种情况。隐式类型转换是件麻烦事,它们很可能导致错误或非预期的函数被调用(参看ME条款5);此外C++也不能在一个转换过程中连续进行多余一次的用户自定义转换操作(即情形二中的转换),如下所示:接上面的代码,A(类型的对象,后略)可被隐式转换为B,B可被隐式转换为C,但A却非常不合逻辑地不可被隐式转换为C。classC{public:C(Bb){};}Aa;Cc;C=a;//错误!

因此应该尽量避免隐式类型转换,为此C++提供了关键字explicit来规避可被单参调用的构造函数引起的隐式类型转换。但标准转换以及隐式类型转换操作符引起的转换只能交由那些追求至善至美的程序员来小心处理了。当然C++语言还是提供了必要的工具来辅助那些追求至善至美的程序员,这些工具就是下面要讲的显式类型转换关键字:static_cast,const_cast,dynamic_cast以及reinterpret_cast。

二,显式类型转换C++是一门强类型转换,因此不同自定义类型之间的转换必须进行显式转换,当然基础数据类型也可以进行显式转换。shorta=10;intb;b=(int)a;//c-likecastnotationb=int(a);//functionalnotation以上是基础数据类型之间进行传统的强制类型转换。这种强制类型转换可以在两种指向不同类型对象的指针之间进行,这很可能是相当危险的事情。所以C++提供四种转换操作符来细分显式类型转换:static_cast<new_type>(expression)

const_cast<new_type>(expression)

dynamic_cast<new_type>(expression)

reinterpret_cast<new_type>(expression)

static_caststatic_cast很像C语言中的旧式类型转换。它能进行基础类型之间的转换,也能将带有可被单参调用的构造函数或用户自定义类型转换操作符的类型转换,还能在存有继承关系的类之间进行转换(即可将基类转换为子类,也可将子类转换为基类),还能将non-const对象转换为const对象(注意:反之则不行,那是const_cast的职责。)。

doubled=3.14159265;inti=static_cast<int>(d);classA{};classB{public:B(Aa){};};Aa;Bb=static_cast<B>(a);classCBase{};classCDerived:publicCBase{};CBase*a=newCBase;CDerived*b=static_cast<CDerived*>(a);

注意:static_cast转换时并不进行运行时安全检查,所以是非安全的,很容易出问题。因此C++引入dynamic_cast来处理安全转型。

dynamic_cast

dynamic_cast主要用来在继承体系中的安全向下转型。它能安全地将指向基类的指针转型为指向子类的指针或引用,并获知转型动作成功是否。如果转型失败会返回null(转型对象为指针时)或抛出异常(转型对象为引用时)。dynamic_cast会动用运行时信息(RTTI)来进行类型安全检查,因此dynamic_cast存在一定的效率损失。(我曾见过属于优化代码80/20法则中的20那一部分的一段游戏代码,起初使用的是dynamic_cast,后来被换成static_cast以提升效率,当然这仅是权宜之策,并非好的设计。)classCBase{};classCDerived:publicCBase{};CBaseb;CBase*pb;CDerivedd;CDerived*pd;pb=dynamic_cast<CBase*>(&d);//ok:derived-to-basepd=dynamic_cast<CDerived*>(&b);//error:base-to-derived

上面的代码中最后一行VS2010会报如下错误:errorC2683:'dynamic_cast':'CBase'isnotapolymorphictype

IntelliSense:theoperandofaruntimedynamic_castmusthaveapolymorphicclasstype这是因为dynamic_cast只有在基类带有虚函数的情况下才允许将基类转换为子类。classCBase{virtualvoiddummy(){}};classCDerived:publicCBase{inta;};intmain(){CBase*pba=newCDerived;CBase*pbb=newCBase;CDerived*pd1,*pd2;pd1=dynamic_cast<CDerived*>(pba);pd2=dynamic_cast<CDerived*>(pbb);return0;}

结果是:上面代码中的pd1不为null,而pd2为null。

dynamic_cast也可在null指针和指向其他类型的指针之间进行转换,也可以将指向类型的指针转换为void指针(基于此,我们可以获取一个对象的内存起始地址constvoid*rawAddress=dynamic_cast<constvoid*>(this);)。

const_cast前面提到const_cast可去除对象的常量性(const),它还可以去除对象的易变性(volatile)。const_cast的唯一职责就在于此,若将const_cast用于其他转型将会报错。voidprint(char*str){cout<<str<<endl;}intmain(){constchar*c="sampletext";print(const_cast<char*>(c));return0;}

reinterpret_castreinterpret_cast用来执行低级转型,如将执行一个int的指针强转为int。其转换结果与编译平台息息相关,不具有可移植性,因此在一般的代码中不常见到它。reinterpret_cast常用的一个用途是转换函数指针类型,即可以将一种类型的函数指针转换为另一种类型的函数指针,但这种转换可能会导致不正确的结果。总之,reinterpret_cast只用于底层代码,一般我们都用不到它,如果你的代码中使用到这种转型,务必明白自己在干什么。

三,typeid:获取表达式的类型typeid定义在标准头文件<typeinfo>中,用于获取表达式的类型,它返回一个数据类型或类名字的字符串。当typeid用于自定义类型时,它使用RTTI信息来获取对象的动态类型。基于typeid,我们可以构建出比较对象(动态)类型的操作。

四,使用原则:尽量避免类型转换操作;优先使用C++风格的转型1,鉴于类型转换的隐蔽,不安全,易引起

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论