`
yangyou230
  • 浏览: 1639637 次
文章分类
社区版块
存档分类

七类型转换

 
阅读更多
<meta content="text/html; charset=utf-8" http-equiv="CONTENT-TYPE"> <meta content="OpenOffice.org 2.2 (Linux)" name="GENERATOR"> <meta content="freebird" name="AUTHOR"> <meta content="20070510;9550000" name="CREATED"> <meta content="root" name="CHANGEDBY"> <meta content="20070717;14010300" name="CHANGED"> <style type="text/css"> <!-- @page { size: 8.5in 11in; margin: 0.79in } H1 { margin-top: 0.24in; margin-bottom: 0.23in; line-height: 200%; page-break-inside: avoid } H1.western { font-family: "Liberation Serif", serif; font-size: 22pt } H1.cjk { font-family: "DejaVu Sans"; font-size: 22pt } H1.ctl { font-family: "DejaVu Sans"; font-size: 22pt } H2 { margin-top: 0.18in; margin-bottom: 0.18in; line-height: 173%; page-break-inside: avoid } H2.western { font-family: "Cambria", serif; font-size: 16pt } H2.cjk { font-family: "宋体", "SimSun"; font-size: 16pt } H2.ctl { font-family: "Times New Roman", serif; font-size: 16pt } P { margin-bottom: 0.08in } --> </style>

类型转换

C++提供六种类型转换符号。前两种是C风格,称为C风格强制转换,(T)或者T(),他们的效果一样。后面四种分别是:

const_cast<T>()

负责将const类型转换为非const类型,也可以反过来转换。

通常非const类型会自动转换成const类型,所以一般不需要使用const_cast进行转换,但是如果有重载函数或者模板特化的话,还是有用的,请看下面的例子:


void f(string& str)

{

cout<<str<<endl;

}


void f(string const& str)

{

cout<<str<<endl;

}




int _tmain(int argc, _TCHAR* argv[])

{

string str("f");

f(const_cast<string const&>(str));

return 0;

}

将调用f(string const& str)版本。

使用const_cast强制将原本const类型转换成非const类型是危险的行为。因为当你声明一个变量是const类型时,编译器有可能将该常量放在ROM中或者受到写保护的RAM页中。当你又试图转换这种使用物理手段来保护的常量时,经常会表现为内存故障。所以,尽可能的避免这样做,而且要意识到,一旦你让一个变量声明为常量,你就应该永不回头。

static_cast<T>()

1)不能替代const_cast

C++标准规定static_cast不能用来将常量类型转换为非常量类型,那要依赖于const_cast。

2)等价于创建临时变量

static_cast可以用于达到类似于创建无具名临时变量的效果,比如:

void f(string const& str)

{

cout<<str<<endl;

}


int _tmain(int argc, _TCHAR* argv[])

{

f(static_cast<string>("h"));

f(string("h"));//你可以理解为C风格强类型转换,也可以理解为创建无具名临时变量

return 0;

}

两个对于f函数的调用都正确,并且标准规定了static_cast<string>(“h”)和string(“h”)效果一样。

3)支持所有隐式转换

编译器支持的隐式转换操作都可以用static_cast完成。当较大的算术类型赋给较小的算术类型时,static_cast将关闭编译器数据有可能丢失的警告。

4)比较安全

static_cast 在编译时使用类型信息执行转换, 在转换执行必要的检测(诸如指针越界计算, 类型检查). 其操作相对是安全的.

int n=9;

double d=static_cast < double > (n);

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

因为它比较安全,所以像下面我这样乱来就不能被编译器接受:

string str;

int* p=static_cast<int*>(&str);

error C2440: 'static_cast' : cannot convert from 'std::string *__w64 ' to 'int *'

相比而言,C风格的强转就是不安全的,因为下面的代码编译器允许:

string str;

int* p=(int*)&str;

说static_cast只是比较安全,是因为这样的代码居然还是能通过:

int x=9;

string* p=static_cast<string*>(&x);

5)void*转换成T*

6)支持向下转型

static_cast可以将指向基类的指针强制转换成指向子类的指针。这不是dynamic_cast做的事情么?它们有什么区别呢?

简单来说,static_cast速度更快,安全性更差,dynamic_cast性能较差,但是更加严格和安全。


dynamic_cast<T>()

dynamic_cast将基类类型对象的引用或者指针转换为同一继承层次中的派生类型的引用或指针。

dynamic_cast涉及运行时类型检查,如果转换指针失败,将返回0,如果转换引用失败,将抛出bad_cast类型的异常。

dynamic_cast首先检查被请求的转换是否有效,如果有效才进行实际的转换。

dynamic_cast的性能是不高的,如果继承的层次较深的话,影响更大,但这不是你转而使用不太安全的static_cast的理由。

比较好的做法是避免向下转型,基类提供更多的虚函数或者直接使用子类都是候选的办法。

reinterpret_cast<T>()

reinterpret_cast是强制编译器接收程序员主观认定的类型。它的行为不同于相对谨慎的static_cast, reinterpret_cast 仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换,上面static_cast的例子修改一下:

int n=9;

double d=reinterpret_cast<double & > (n);

这次, 结果有所不同. 在进行计算以后, d 包含无用值. 这是因为 reinterpret_cast 仅仅是复制 n 的比特位到 d, 没有进行必要的分析.所以小心使用reinterpret_cast,和C风格的强转一样的不安全。

不仅如此,reinterpret_cast的执行后果根据不同的编译器上行为很可能不一样,没有可移植性。

既不安全又没有可移植性,那要它干么?因为有些与特定系统相关的底层编程,要求使用它在端口串行输入和输出数据,或者转换某些地址中的整数。

作为一个较安全的措施,我们可以这样干:

T1* p1=...;

T2* p2=reinterpret_cast<T2*>(p1)

第二行换成如下代码:

void* pV=p1;

T2* p2=static_cast<T2*>(pV);

尽量少用reinterpret_cast,如果实在不行,试试用static_cast替代来降低风险提高移植性。


用C++转换代替C风格转换

当你写下任何一种转换操作,编译器都会在幕后写出一些代码,比如找到目标类型的类型信息和内存布局,以便执行转换。

假如你写下如下C风格代码:

class Derived;


void Gun(Base* pb)

{

Derived* pd=(Derived*)pb;


}

你没有#include “Derived.h”,而是通过前置声明了Derived类型,C风格转换会让你编译通过,但是由于看不到Derived.h文件,所以编译器会假定Base和Derived是两个不相关的类型,不会对对象内存布局作必要的调整,结果是运行时可能莫名其妙崩溃。

而这种情况下如果你使用了C++风格的转换,将会提示不能转换的错误,便于保证程序的正确性。

C++风格的转换操作符更容易搜索。

分享到:
评论

相关推荐

    Spring MVC学习(七)-------SpringMVC数据类型转换

    Spring MVC学习(七)-------SpringMVC数据类型转换

    VC CString最全面的总结 常用数据类型使用转换详解等总结

    一、其它数据类型转换为字符串 15 二、从其它包含字符串的变量中获取指向该字符串的指针 16 三、字符串转换为其它数据类型 16 四、其它数据类型转换到CString 16 五、BSTR、_bstr_t与CComBSTR 16 六、VARIANT 、_...

    python数据类型转换代码

    进行数据类型转换,是学习廖雪峰网站上学习到的知识。

    文本转换-七种类型-易语言编写

    七种类型分别为: ------------------------------------------------------------ 1、#GBK到BIG5; 2、#BIG5到GBK; 3、#GBK繁体到简体; 4、#GBK简体到繁体; 5、#BIG5到GBK简体; 6、#GBK到SJIS; 7、#SJIS到GBK...

    地理坐标转换小工具集

    坐标转换小工具,支持北京54,西安80,wgs84下经纬度和xy坐标系之间的转换,可设置四参数、七参数,空间直角坐标系,大地坐标,平面坐标等类型的转换

    1954北京坐标转80大地坐标转换软件

    WGS-84坐标和北京54坐标是不同两个椭球的坐标转换,所以要求得三参数或七参数,而北京54和佛山坐标都是同一个椭球,所以他们之间的转换是地方坐标转换,需要求得地方转化四参数,因为要求得到的北京54是平面坐标所以...

    易源码-文本转换-七种类型

    七种类型分别为: ---------------------------------------------------------- 1、#GBK到BIG5; 2、#BIG5到GBK; 3、#GBK繁体到简体; 4、#GBK简体到繁体; 5、#BIG5到GBK简体; 6、#GBK到SJIS; 7、#SJIS到GBK。

    地理坐标转换小工具集(GIS)

    坐标转换小工具,支持北京54,西安80,wgs84下经纬度和xy坐标系之间的转换,可设置四参数、七参数,空间直角坐标系,大地坐标,平面坐标等类型的转换

    sql使用cast进行数据类型转换示例

    详解SQL Server中的数据类型详解MySQL数据类型int(M)中M的含义mysql存储引擎和数据类型(二)Java数据类型与MySql数据类型对照表SQL Server数据类型转换方法SQL Server比较常见数据类型详解SQLite教程(七):...

    地图投影及坐标转换软件

    本软件是一款集地图投影、坐标转换、GPS高程拟合和常用...坐标转换包括三参数、七参数、仿射变换(线性)等转换方式;源坐标和目标坐标可设置,包括椭球、投影方式和坐标类型(大地坐标、平面坐标和空间直角坐标)。

    动网dvbbs 6.0 to lb雷傲转换程序

    七、其他 八、声明 ================ 一、简介 此程序使用 VBScript 编制而成,用于动网到雷傲的数据转换。 此程序须在本地执行,无法在服务器上执行,除非你能直接控制服务器。 ...

    大小写金额转换-源码

    不得用一、二(两)、三、四、五、六、七、八、九、十、念、毛、另(或0)填写,不得自造简化字。如果金额数字书写中使用繁体字,如貳、陸、億、萬、圓的,也应受理。 二、中文大写金额数字到“元”为止的,在“元”...

    源代码下载——第七章 注解式控制器的数据验证、类型转换及格式化

    NULL 博文链接:https://jinnianshilongnian.iteye.com/blog/1739306

    易语言使用通用型

    易语言使用通用型源码,使用通用型,模板,子程序1,强制转换,指针到整数,取通用类型,置名字,取名字,IsBadReadPtr,GlobalSize,CopyMemory,SendMessage

    SQL学习笔记七函数 数字,日期,类型转换,空值处理,case

    SQL学习笔记七函数 数字,日期,类型转换,空值处理,case 使用说明

    地图投影、坐标转换、GPS高程拟合和常用测绘工具

    坐标转换包括三参数、七参数、仿射变换(线性)等转换方式;源坐标和目标坐标可设置,包括椭球、投影方式和坐标类型(大地坐标、平面坐标和空间直角坐标)。 &lt;br&gt;GPS高程包括12种拟合方法。 &lt;br&gt;测量工具多多...

    C++中字符串与整型浮点型间的转换.

    C++中字符串与整型浮点型间的转换或者与其他类型之间的转换是我们经常遇到的问题,本人总结了一下网上的资源,与大家分享一下

    JAVA中string数据类型转换详解

    在JAVA中string是final类,提供字符串不可以修改,string类型在项目中经常使用,下面给大家介绍了string七种数据类型转换,需要的朋友可以参考下

    struts2(1-7)源码 struts2学习入门 源码学习

    struts2 将要进行自定义类型转换的点数据从1个增加到3个 struts3 进行全局的类型转换 struts4 使用Struts2中内部类中的方法进行自定义类型转换,用到的类StrutsTypeConverter struts5 增加集合类型,使用范型 ...

    C#.Net基础5 基础入门知识 数据类型 范例 ppt 实例 可以直接运行

    枚举同样也可以跟string类型互相转换,如果将枚举类型转换成string类型,则直接调用ToString(). 如果将字符串转换成枚举类型则需要下面这样一行代码: (要转换的枚举类型)Enum.Parse(typeof(要转换的枚举类型),"要...

Global site tag (gtag.js) - Google Analytics