文档章节

代码笔记2014-5-9

树叶先生
 树叶先生
发布于 2014/05/09 12:59
字数 2837
阅读 20
收藏 0

明天就要期中考试啦!!!

鸡冻死了,冒雨到图书馆鞋子都湿了这会儿脚冻死了~~


好啦言归正传。

因为期中考所以要复习。结果看到一道选择题。是关于cast类型转换的。之前完全没概念,赶快google~_~

有了一个大牛的技术贴!但他也是转载的!我忍不住要全文转啦!(我有小改动= =)

这次先po地址:http://welfare.cnblogs.com/articles/336091.html

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

(第一PART)

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

A:转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符。比如,为了转换一个类型为doubole的浮点数的指针到整型:
代码:
int i;
double d;
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)



1.reinterpret_cast


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

如果情况是从一个指针到整型的拷贝,内容的解释是系统相关的,所以任何的实现都不是方便的。

一个转换到足够大的整型能够包含它的指针是能够转换回有效的指针的。

代码:
class A {};
class B {};

A * a = new A;
B * b = reinterpret_cast<B *>(a);


'reinterpret_cast'就像传统的类型转换一样对待所有指针的类型转换。

2.static_cast

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

应用到类的指针上,意思是说它允许子类类型的指针转换为父类类型的指针(这是一个有效的隐式转换).

同时,也能够执行相反动作:转换父类为它的子类。

代码:
class Base {};
class Derived : public Base {};

Base *a = new Base;
Derived *b = static_cast<Derived *>(a);

在这最后例子里,被转换的父类没有被检查是否与目的类型相一致。

'static_cast'除了操作类型指针,也能用于执行类型定义的显式的转换,以及基础类型之间的标准转换:

代码:
double d = 3.14159265;
int    i = static_cast<int>(d);

(树叶:所以我想说static_cast一般是用于基类和子类之间的?)


3.dynamic_cast

'dynamic_cast' 只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。

不过,与static_cast不同,在隐式转换的相反过程里,dynamic_cast会检查操作是否有效

也就是说,它会检查转换是否会返回一个被请求的有效的完整对象

检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL。

代码:
class Base { virtual dummy() {} };
class Derived : public Base {};

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的异常类型被抛出:

代码:
class Base { virtual dummy() {} };
class Derived : public Base { };

Base* b1 = new Derived;
Base* b2 = new Base;

Derived d1 = dynamic_cast<Derived &*>(b1);          // succeeds
Derived d2 = dynamic_cast<Derived &*>(b2);          // fails: exception thrown

4.const_cast

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

代码:
class C {};


const C *a = new C;

C *b = const_cast<C *>(a);

其它三种操作符是不能修改一个对象的常量性的。
注意:'const_cast'也能改变一个类型的volatile qualifier。

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

(第二PART,基本没看了 = =)
  C++ 同时提供了四种新的强制转型形式(通常称为新风格的或 C++ 风格的强制转型):
  const_cast(expression)
  dynamic_cast(expression)
  reinterpret_cast(expression)
  static_cast(expression)

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

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

class B { ... };
class D : public B { ... };

void f(D* pb)
{
   D* pd1 = dynamic_cast<D*>(pb);
   D* pd2 = static_cast<D*>(pb);
}


If pb really points to an object of type D, then pd1 and pd2 will get the same value. They will also get the same value if pb == 0. (树叶翻译:如果pb是指向D类的指针,或者pb =NULL,那么pd1和pd2将得到相同值)

void f(B* pb)
{
   D* pd1 = dynamic_cast<D*>(pb);      //Error!
   D* pd2 = static_cast<D*>(pb);        //succeed(我测试了的!)
}

If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to return zero. However, static_cast relies on the programmer’s assertion that pb points to an object of type D and simply returns a pointer to that supposed D object.(树叶:如果pb指向的是B,如上,pb1将返回NULL;pb2的返回取决于程序员的需求,即pb会指向一个D的对象并返回这个指针,但其实这个D类是虚构的)

即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 仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换, 例子如下:

    int n=9;

    double d=static_cast < double > (n);

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

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


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

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

(然后底下有一条评论我觉得也蛮有用= =)

static_cast: 在功能上基本上与C风格的类型转换一样强大,含义也一样。它也有功能上限制。例如,你不能用static_cast象用C风格的类型转换一样把 struct转换成int类型或者把double类型转换成指针类型,另外,static_cast不能从表达式中去除const属性,因为另一个新的类 型转换操作符const_cast有这样的功能。

const_cast: 用于类型转换掉表达式的const或volatileness属性。通过使用const_cast,你向人们和编译器强调你通过类型转换想做的只是改变一 些东西的constness或者 volatileness属性。这个含义被编译器所约束。如果你试图使用const_cast来完成修改constness 或者volatileness属性之外的事情,你的类型转换将被拒绝。

dynamic_cast: 它被用于安全地沿着类的继承关系向下进行类型转换。这就是说,你能用dynamic_cast把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用,而且你能知道转换是否成功。失败的转换将返回空指针(当对指针进行类型转换时)或者抛出异常(当对引用进行类型转换时)。

reinterpret_cast: 使用这个操作符的类型转换,其的转换结果几乎都是执行期定义(implementation-defined)。因此,使用 reinterpret_casts的代码很难移植。reinterpret_casts的最普通的用途就是在函数指针类型之间进行转换。

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


摘完了。附上我做的那道题

Suppose you declared GeometricObject *p = &object. To cast p to Circle, use ______.

(把G类型指针p转化成C类型)

A

Circle p1 = (Circle)(*p); 

B

Circle *p1 = dynamic_cast<Circle*>(p); 

C

Circle *p1 = dynamic_cast<Circle>(p); 

D

Circle p1 = static_cast<Circle>(*p); 

答案应该是B。

很明显C类应该是G的派生类(Geometric,几何;Circle,圆)

而这是典型的继承关系向下进行类型转换~~故用dunamic_cast!

其实也可以用static_cast的吧。只不过哦D答案那里不是Ciecle*。

Yes,我懂了!


© 著作权归作者所有

上一篇: 代码笔记2014-4-22
下一篇: 代码笔记-2014-4-24
树叶先生
粉丝 0
博文 4
码字总数 4660
作品 0
广州
私信 提问
ios8新特性屏幕适配之sizeclass

ios8推出也有一段时间了,由于时间比较紧,所以没去学习ios8的新特性,随着iphone6,6+的推出,ios屏幕适配是一个大问题,如何成功适配各种尺寸以及ipad呢?苹果公司为了解决这个问题给出了新...

哥特复心
2014/12/08
10.3K
0
ggplot2学习笔记系列之利用ggplot2绘制误差棒及显著性标记

绘制带有误差棒的条形图 library(ggplot2) #创建数据集 df <- data.frame(treatment = factor(c(1, 1, 1, 2, 2, 2, 3, 3, 3)), response = c(2, 5, 4, 6, 9, 7, 3, 5, 8), group = factor(c......

R语言中文社区
2018/02/12
0
0
caffe资源汇总(更新中)

学习需要更新,网上有一些非常不错博客,首先感谢这些博主,他们都很认真。其次是这些笔记。 1、xizero00 2、lingerlanlan 3、iamzhangzhuping 4、zhangwang 5、yhl_leo 6、在路上 7、s...

langb2014
2016/05/31
0
0
读《PHP和MySQL Web开发》

【第一部分】PHP基础与入门 1、PHP学习笔记1:基础知识快速浏览 http://my.oschina.net/bluefly/blog/472673 2、PHP学习笔记2:文件 http://my.oschina.net/bluefly/blog/477601 3、PHP学习笔...

slyso
2015/07/14
455
0
Spark 学习资源收集

(一)spark 相关安装部署、开发环境 1、Spark 伪分布式 & 全分布式 安装指南 http://my.oschina.net/leejun2005/blog/394928 2、Apache Spark探秘:三种分布式部署方式比较 http://dongxic...

openthings
2016/05/29
201
0

没有更多内容

加载失败,请刷新页面

加载更多

64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
今天
13
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
今天
7
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
今天
12
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
今天
12
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部