[转]C++四种cast操作符
http://blog.csdn.net/starryheavens/article/details/4617637
C 风格(C-style)强制转型如下:
(T) expression 或
T(expression) //函数风格(Function-style)
两种形式之间没有本质上的不同。
对于具有转换的简单类型而言C 风格转型工作得很好。然而,这样的转换符也能不分皂白地应用于类(class)和类的指针。ANSI-C++标准定义了四个新的转换符:reinterpret_cast, static_cast, dynamic_cast和const_cast,目的在于控制类(class)之间的类型转换。
1.1 reinpreter_cast
用法:reinpreter_cast<type-id> (expression)
type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。
这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。reinpreter_cast是特意用于底层的强制转型,导致实现依赖(就是说,不可移植)的结果。
int n=9;
// reinterpret_cast 仅仅是复制 n 的比特位到 d,因此d 包含无用值。
double d=reinterpret_cast<double & > (n);
1.2 const_cast
用法:const_cast<type_id> (expression)
用于修改类型的const或volatile属性。除了const 或volatile修饰之外,type_id和expression的类型是一样的,一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型,而C不提供消除const的机制(已验证)。
常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
1.3 static_cast
用法:static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它允许执行任意的隐式转换和相反转换动作。主要有如下几种用法:
1)用于基本数据类型之间的转换,如把int转换成char,non-const 对象转型为 const 对象(这里相反方向不可以,C++只有const_cast可以)。
2)把空指针转换成目标类型的指针。(之前的做法是用强制转换(type-id*))
3)把任何类型的表达式转换成void类型。
4)应用到类的指针上,它允许子类类型的指针转换为父类类型的指针(upercasting这是一个有效的隐式转换);也能够执行相反动作,即转换父类为它的子类(downcasting),这种转换的安全性需要开发人员来保证(主要是在非上下转型中)。
class Base {};
class Derived : public Base {};
Base *a = new Base;
Derived *b = NULL;
b = static_cast<Derived *>(a); //可以通过编译,但存在安全隐患(如访问//Derived的成员)
注意:
1.static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
2.在非基本类型或上下转型中,被转换的父类需要检查是否与目的类型相一致,否则,如果在两个完全不相干的类之间进行转换,将会导致编译出错。
1.4 dynamic_cast
只用于对象的指针和引用,主要用于执行“安全的向下转型”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。
当用于多态类型时(包含虚函数),它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里(即隐式转换的相反过程),dynamic_cast根据RTTI信息检查操作是否有效。即在转换时dynamic_cast会检查转换是否能返回一个被请求的有效的完整对象。这种检查不是语法上的,而是真实情况的检查。检测在运行时进行,如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL。
先看RTTI相关部分,通常,许多编译器都是通过vtable找到对象的RTTI信息的,这也就意味着,如果基类没有虚函数,也就无法判断一个基类指针变量所指对象的真实类型, 这时候dynamic_cast只能用来做安全的转换(upercasting),如从派生类指针转换成基类指针,而这种转换其实并不需要dynamic_cast参与。
class Base { virtual dummy() {} };
class Derived : public Base {};
class Other{} ;
Base* b1 = new Derived;
Base* b2 = new Base;
Derived* d1 = dynamic_cast<Derived *>(b1); // succeeds
Derived* d2 = dynamic_cast<Derived *>(b2); // fails: returns 'NULL'
//如果一个引用类型执行了类型转换并且这个转换是不可能的,运行时一个//bad_cast的异常类型会被抛出:
Derived d3 = dynamic_cast<Derived &>(*b1); // succeeds
Derived d4 = dynamic_cast<Derived &>(*b2); // fails: exception thrown
注意:Base需要有虚函数,否则会编译出错。
1.5 小结
四种类型转换操作符对于隐式的类型转换没有必要。
static_cast在更宽上范围内可以完成映射,这种不加限制的映射伴随着不安全性。在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时(基类需要包含虚函数),dynamic_cast具有类型检查的功能,牺牲了效率,但比static_cast安全。
[转]C++四种cast操作符的更多相关文章
- C++四种cast操作符
C 风格(C-style)强制转型如下: (T) expression 或 T(expression) //函数风格(Function-style) 两种形式之间没有本质上的不同. 对于具有转换的简 ...
- C++的四种cast操作符的区别--类型转换(转)
转自: http://welfare.cnblogs.com/articles/336091.html Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 r ...
- C++的四种cast操作符的区别--类型转换
Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意? A:转换的含义是通过改变一个变量的类型为别的类型从而 ...
- C++中的四种转型操作符
在具体介绍C++中的四种转型操作符之前,我们先来说说旧式转型的缺点: ①它差点儿同意将不论什么类型转换为不论什么其它类型,这是十分拙劣的.假设每次转型都可以更精确地指明意图,则更好. ②旧式转型难以辨 ...
- 面试问题之C++语言:说一说C++中四种cast转换
C++中四种类型转换是:static_cast.dynamic_cast.const_cast.reinterpret_cast 1.const_cast 常量转换,用于将const变量转为非cons ...
- C++的四种强制转型形式:
C++同时提供了四种新的强制转型形式(通常称为新风格的或C++风格的强制转型): const_cast(expression)dynamic_cast(expression)reinterpret_c ...
- 【转】C++四种类型转换方式
C++四种类型转换方式 https://blog.csdn.net/lv_amelia/article/details/79483579 C风格的强制类型转换(Type Case)很简单,不管什么类型 ...
- C++中四种类型转换以及const_cast是否能改变常量的问题
we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...
- [C++][操作符]四种显示转换操作符
整理了C++ Primer中提到的四种显示转换,用思维导图写出来,是不是很清晰O(∩_∩)O.
随机推荐
- WPF 绑定二(绑定指定的字符串)
xaml: <Window x:Class="WpfApplication1.Window2" xmlns="http://schemas.microsoft.co ...
- emmet(Zen coding)帮助文档
葵花宝典终可成,半途而废万事空. 官方地址:http://docs.emmet.io/cheat-sheet/ 我导出了pdf版,需要的同学可以下载: 链接:http://pan.baidu.com/ ...
- php取得当前访问url文件名的几种方法
php下获取当前访问的文件名的几种方法.推荐函数:一是PHP获取当前页面的网址: dedecms用的也是这个哦. <?php //获得当前的脚本网址 function GetCurUrl() { ...
- Mysql 正则获取字段的交集【转】
问题描述 比如table1中有两条记录 name no a 2,9 b 8,10 然后有一串字符串,是0,1,2,3,4 然后通过一条sql,找出no为2,9的记录来``` 因为字符串中有 ...
- Asp.net MVC知识积累
一.知识积累 http://yuangang.cnblogs.com/ 跟蓝狐学mvc教程专题目录:http://www.lanhusoft.com/Article/169.html 依赖注入:htt ...
- Linq中延迟查询和立即查询
//立即查询 public static void NowExecute() { var results = new int[]{5,4,3,2,1,6,7,8,9,0 }; int i = 0; v ...
- SQLserver Delete from where 与Oracle delete from where 的差异
1.SQLserver 版本: select @@version; Microsoft SQL Server 2012 (SP1) - 11.0.3128.0 (X64) Dec 28 2012 20 ...
- python 字典内置方法get应用
python字典内置方法get应用,如果我们需要获取字典值的话,我们有两种方法,一个是通过dict['key'],另外一个就是dict.get()方法. 今天给大家分享的就是字典的get()方法. 这 ...
- Hive内表和外表的区别
本文以例子的形式介绍一下Hive内表和外表的区别.例子共有4个:不带分区的内表.带分区的内表.不带分区的外表.带分区的外表. 1 不带分区的内表 #创建表 create table innerTabl ...
- Java之this详解
1. this是指当前对象自己. 用类名定义一个变量的时候,定义的应该只是一个引用,外面可以通过这个引用来访问这个类里面的属性和方法,那们类里面是够也应该有一个引用来访问自己的属性和方法纳?呵呵,JA ...