• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C++中4种类型转换方式 cast操作详解

C++中4种类型转换方式 cast操作详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c++ static cast,c++ dynamic cast,c++ const cast,c++指针详解,c++编程实例详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Q:什么是C风格转换?什么是static_cast,dynamic_cast以及reinterpret_cast?区别是什么?为什么要注意?

A:转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符。比如,为了转换一个类型为doubole的浮点数的指针到整型:
代码:
inti;
doubled;

i=(int)d;
或者:

i=int(d);

对于具有标准定义转换的简单类型而言工作的很好。然而,这样的转换符也能不分皂白的应用于类(class)和类的指针。ANSI-C++标准定义了四个新的转换符:'reinterpret_cast','static_cast','dynamic_cast'和'const_cast',目的在于控制类(class)之间的类型转换。
代码:
reinterpret_cast<new_type>(expression)
dynamic_cast<new_type>(expression)
static_cast<new_type>(expression)
const_cast<new_type>(expression)

1reinterpret_cast

'reinterpret_cast'转换一个指针为其它类型的指针。它也允许从一个指针转换为整数类型。反之亦然。(译注:是指针具体的地址值作为整数值?)
这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。

如果情况是从一个指针到整型的拷贝,内容的解释是系统相关的,所以任何的实现都不是方便的。一个转换到足够大的整型能够包含它的指针是能够转换回有效的指针的。

代码:
classA{};
classB{};

A*a=newA;
B*b=reinterpret_cast<B*>(a);
'reinterpret_cast'就像传统的类型转换一样对待所有指针的类型转换。

2static_cast

'static_cast'允许执行任意的隐式转换和相反转换动作。(即使它是不允许隐式的)

应用到类的指针上,意思是说它允许子类类型的指针转换为父类类型的指针(这是一个有效的隐式转换),同时,也能够执行相反动作:转换父类为它的子类。

在这最后例子里,被转换的父类没有被检查是否与目的类型相一致。
代码:
classBase{};
classDerived:publicBase{};

Base*a=newBase;
Derived*b=static_cast<Derived*>(a);
'static_cast'除了操作类型指针,也能用于执行类型定义的显式的转换,以及基础类型之间的标准转换:

代码:
doubled=3.14159265;
inti=static_cast<int>(d);

3dynamic_cast

'dynamic_cast'只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里(注:即隐式转换的相反过程),dynamic_cast会检查操作是否有效。也就是说,它会检查转换是否会返回一个被请求的有效的完整对象。

检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL.
代码:
classBase{virtualdummy(){}};
classDerived:publicBase{};

Base*b1=newDerived;
Base*b2=newBase;

Derived*d1=dynamic_cast<Derived*>(b1);//succeeds
Derived*d2=dynamic_cast<Derived*>(b2);//fails:returns'NULL'

如果一个引用类型执行了类型转换并且这个转换是不可能的,一个bad_cast的异常类型被抛出:
代码:
classBase{virtualdummy(){}};
classDerived:publicBase{};

Base*b1=newDerived;
Base*b2=newBase;

Derivedd1=dynamic_cast<Derived&*>(b1);//succeeds
Derivedd2=dynamic_cast<Derived&*>(b2);//fails:exceptionthrown

4const_cast

这个转换类型操纵传递对象的const属性,或者是设置或者是移除:
代码:
classC{};

constC*a=newC;

C*b=const_cast<C*>(a);
其它三种操作符是不能修改一个对象的常量性的。
注意:'const_cast'也能改变一个类型的volatilequalifier。

--------------------------------------------------------------------

C++的4种类型转换

一、C风格(C-style)强制转型如下:

(T)expression//castexpressiontobeoftypeT
函数风格(Function-style)强制转型使用这样的语法:
T(expression)//castexpressiontobeoftypeT
这两种形式之间没有本质上的不同,它纯粹就是一个把括号放在哪的问题。我把这两种形式称为旧风格(old-style)的强制转型。

二、C++的四种强制转型形式:

C++同时提供了四种新的强制转型形式(通常称为新风格的或C++风格的强制转型):
const_cast(expression)
dynamic_cast(expression)
reinterpret_cast(expression)
static_cast(expression)

每一种适用于特定的目的:

·dynamic_cast主要用于执行“安全的向下转型(safedowncasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。

·static_cast可以被用于强制隐型转换(例如,non-const对象转型为const对象,int转型为double,等等),它还可以用于很多这样的转换的反向转换(例如,void*指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个const对象转型为non-const对象(只有const_cast能做到),它最接近于C-style的转换。

·const_cast一般用于强制消除对象的常量性。它是唯一能做到这一点的C++风格的强制转型。

·reinterpret_cast是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。

旧风格的强制转型依然合法,但是新的形式更可取。首先,在代码中它们更容易识别(无论是人还是像grep这样的工具都是如此),这样就简化了在代码中寻找类型系统被破坏的地方的过程。第二,更精确地指定每一个强制转型的目的,使得编译器诊断使用错误成为可能。例如,如果你试图使用一个const_cast以外的新风格强制转型来消除常量性,你的代码将无法编译。

==
==dynamic_cast.vs.static_cast
==

classB{...};
classD:publicB{...};

voidf(B*pb)
{
D*pd1=dynamic_cast<D*>(pb);
D*pd2=static_cast<D*>(pb);
}

IfpbreallypointstoanobjectoftypeD,thenpd1andpd2willgetthesamevalue.Theywillalsogetthesamevalueifpb==0.

IfpbpointstoanobjectoftypeBandnottothecompleteDclass,thendynamic_castwillknowenoughtoreturnzero.However,static_castreliesontheprogrammer'sassertionthatpbpointstoanobjectoftypeDandsimplyreturnsapointertothatsupposedDobject.

即dynamic_cast可用于继承体系中的向下转型,即将基类指针转换为派生类指针,比static_cast更严格更安全。dynamic_cast在执行效率上比static_cast要差一些,但static_cast在更宽上范围内可以完成映射,这种不加限制的映射伴随着不安全性.static_cast覆盖的变换类型除类层次的静态导航以外,还包括无映射变换,窄化变换(这种变换会导致对象切片,丢失信息),用VOID*的强制变换,隐式类型变换等...


==
==static_cast.vs.reinterpret_cast
==

reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它.我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的.(这句话是C++编程思想中的原话)

static_cast和reinterpret_cast操作符修改了操作数类型.它们不是互逆的;static_cast在编译时使用类型信息执行转换,在转换执行必要的检测(诸如指针越界计算,类型检查).其操作数相对是安全的.另一方面,reinterpret_cast仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换,例子如下:

intn=9;doubled=static_cast<double>(n);

上面的例子中,我们将一个变量从int转换到double.这些类型的二进制表达式是不同的.要将整数9转换到双精度整数9,static_cast需要正确地为双精度整数d补足比特位.其结果为9.0.而reinterpret_cast的行为却不同:

intn=9;
doubled=reinterpret_cast<double&>(n);

这次,结果有所不同.在进行计算以后,d包含无用值.这是因为reinterpret_cast仅仅是复制n的比特位到d,没有进行必要的分析.

总结:

一共四种cast。
1、static_cast,支持子类指针到父类指针的转换,并根据实际情况调整指针的值,反过来也支持,但会给出编译警告,它作用最类似C风格的“强制转换”,一般来说可认为它是安全的;

2、dynamic_cast,支持父类指针到子类指针的转换,并根据实际情况调整指针的值,和static_cast不同,反过来它就不支持了,会导致编译错误,这种转换是最安全的转换;

3、reinterpret_cast,支持任何转换,但仅仅是如它的名字所描述的那样“重解释”而已,不会对指针的值进行任何调整,用它完全可以做到“指鹿为马”,但很明显,它是最不安全的转换,使用它的时候,你得头脑清醒,知道自己在干什么;

4、const_cast,这个转换能剥离一个对象的const属

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 由static_cast和dynamic_cast到C++对象占用内存的全面分析
  • 解析C++编程中的bad_cast异常
  • C++中4种类型转换方式 cast操作详解
  • 关于C++中的static关键字的总结
  • C++中四种对象生存期和作用域以及static的用法总结分析
  • 解析static在C和C++中的用法以及区别
  • 从汇编看c++中函数里面的static关键字的使用说明

相关文章

  • 2017-05-28C++输出斐波那契数列的两种实现方法
  • 2017-05-28C语言 解决不用+、-、×、÷数字运算符做加法的实现方法
  • 2017-05-28win32 api实现2048游戏示例
  • 2017-05-28C语言程序设计50例(经典收藏)
  • 2017-05-28内核线程优先级设置的方法介绍
  • 2017-05-28C语言中的强符号和弱符号介绍
  • 2017-05-28C语言使用回溯法解旅行售货员问题与图的m着色问题
  • 2017-05-28C++堆排序算法的实现方法
  • 2017-05-28C语言实现返回字符串函数的四种方法
  • 2017-05-28C++ using namespace std 用法深入解析

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 使用map实现单词转换的实例分析
    • 用C语言举例讲解数据结构中的算法复杂度结与顺序表
    • 详解C++编程中标记语句与复合语句的写法
    • C 语言基础教程(我的C之旅开始了)[二]
    • 编译错误error: stray ‘\343’in program的解决方法
    • 构造函数不能声明为虚函数的原因及分析
    • C语言fgets和fputs函数的用法详解(以字符串的形式读写文件)
    • 枚举和宏的区别详细解析
    • C语言编写Linux守护进程实例
    • C++利用链栈实现表达式求值

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有