条款2:最好使用C++转型操作符(1)

想想低阶转型动作。它几乎像goto一样被视为程序设计上的"贱民"。尽管如此,它却仍能够苟延残喘,因为当某种情况愈来愈糟,转型可能是必要的。是的,当某种情况愈来愈糟,转型是必要的!

不过,旧式的C转型方式并非是唯一选择。它几乎允许你将任何类型转换为任何其他类型,这是十分拙劣的。如果每次转型都能够更精确地指明意图,则更好。举个例子,将一个 pointer-to-const-object 转型为一个 pointer-to-non-const-object(也就是说只改变对象的常量性),和将一个 pointer-to-base-class-object 转型为一个pointer-to-derived-class-object(也就是完全改变了一个对象的类型),其间有很大的差异。传统的 C 转型动作对此并无区分(这应该不会造成你的惊讶,因为 C 式转型是为 C 设计的,不是为了 C++)。

旧式转型的第二个问题是它们难以辨识。旧式转型的语法结构是由一对小括号加上一个对象名称(标识符)组成,而小括号和对象名称在 C++ 的任何地方都有可能被使用。因此,我们简直无法回答最基本的转型相关问题"这个程序中有使用任何转型动作吗?"。因为人们很可能对转型动作视而不见,而诸如 grep 之类的工具又无法区分语法上极类似的一些非转型写法。

为解决C 旧式转型的缺点,C++ 导入4个新的转型操作符(cast operators):static_cast,const_cast,dynamic_cast 和reinterpret_cast。对大部分使用目的而言,面对这些操作符你唯一需要知道的便是,过去习惯的写码形式:

  1. (type) expression

    现在应该改为这样:

    1. static_cast(expression)

      举个例子,假设你想要将一个 int 转型为一个double,以强迫一个整数表达式导出一个浮点数值来。采用 C 旧式转型,可以这么做:

      1. int firstNumber, secondNumber; ...
      2. double result = ((double)firstNumber)/secondNumber;

        如果采用新的 C++ 转型法,应该这么写:

        1. double result = static_cast(firstNumber)/secondNumber;

          这种形式十分容易被辨识出来,不论是对人类或是对工具程序而言。

          static_cast 基本上拥有与 C 旧式转型相同的威力与意义,以及相同的限制。例如,你不能够利用 static_cast 将一个 struct 转型为int,或将一个 double 转型为 pointer;这些都是 C 旧式转型动作原本就不可以完成的任务。static_cast 甚至不能够移除表达式的常量性(constness),因为有一个新式转型操作符 const_cast 专司此职。

          其他新式 C++ 转型操作符适用于更集中(范围更狭窄)的目的。const_cast 用来改变表达式中的常量性(constness)或变易性(volatileness)。使用 const_cast, 便是对人类(以及编译器)强调 ,通过这个转型操作符,你唯一打算改变的是某物的常量性或变易性。这项意愿将由编译器贯彻执行。如果你将 const_cast 应用于上述以外的用途,那么转型动作会被拒绝。下面是个例子:

          1. class Widget { ... }; class SpecialWidget: public Widget { ... };
          2. void update(SpecialWidget *psw); SpecialWidget sw; // sw 是个 non-const 对象,
          3. const SpecialWidget& csw = sw; // csw 却是一个代表 sw 的 reference, // 并视之为一个 const 对象。
          4. update(&csw); // 错误!不能将 const SpecialWidget*
          5. // 传给一个需要 SpecialWidget* 的函数。
          6. update(const_cast(&csw)); // 可!&csw 的常量性被去除了。也因此,
          7. // csw(亦即 sw)在此函数中可被更改。
          8. update((SpecialWidget*)&csw); // 情况同上,但使用的是较难辨识
          9. // 的 C 旧式转型语法。
          10. Widget *pw = new SpecialWidget; update(pw); // 错误!pw 的类型是 Widget*,但
          11. // update() 需要的却是 SpecialWidget*。
          12. update(const_cast(pw)); // 错误!const_cast 只能用来影响
          13. // 常量性或变易性,无法进行继承体系 // 的向下转型(cast down)动作。

            显然,const_cast 最常见的用途就是将某个对象的常量性去除掉。

            第二个特殊化的转型操作符是dynamic_cast,用来执行继承体系中"安全的向下转型或跨系转型动作"。也就是说你可以利用 dynamic_cast,将"指向 base class objects的pointers或references"转型为"指向derived(或sibling base)class objects 的 pointers 或 references",并得知转型是否成功 。如果转型失败,会以一个 null 指针(当转型对象是指针)或一个 exception(当转型对象是 reference)表现出来:

            1. Widget *pw; ...
            2. update(dynamic_cast(pw)); // 很好,传给 update() 一个指针,指向
            3. // pw 所指的 SpecialWidget--如果 pw // 真的指向这样的东西;否则传过去的
            4. // 将是一个 null 指针。
            5. void updateViaRef(SpecialWidget& rsw);
            6. updateViaRef(dynamic_cast(*pw)); // 很好,传给 updateViaRef() 的是
            7. // pw 所指的 SpecialWidget--如果 // pw 真的指向这样的东西;否则
            8. // 抛出一个 exception。
              点击复制链接 与好友分享!回本站首页
              您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力
              上一篇:C++中的转型操作符:static_case const_cast dynamic_cast reinterpret_cast
              下一篇:条款2:最好使用C++转型操作符
              相关文章

              条款23宁以non-member函数代替member函

              Effective C++ 条款总结 读书笔记(

              《Effective C++》学习笔记条款21 必

              条款2:最好使用C++转型操作符

              《Effective C++》学习笔记条款27 尽

              《Effective C++》学习笔记条款33 避

              Effective C++:条款18:让接口容易被

              Effective C++:条款17:以独立语句将

              Effective C++:条款21:必须返回对象

              Effective C++:条款20:宁以 pass-

              图文推荐
              条款2:最好使用C++转型操作符(1)
              ZOJ 3640 Help Me
              条款2:最好使用C++转型操作符(1)
              CF 518C(Anya and
              条款2:最好使用C++转型操作符(1)
              hdu 1016 Prime R
              UVA - 11987 - A

分类:默认分类 时间:2012-01-09 人气:1
本文关键词:
分享到:

相关文章

Copyright (C) quwantang.com, All Rights Reserved.

趣玩堂 版权所有 京ICP备15002868号

processed in 0.064 (s). 9 q(s)