Item2: Prefer C++-style casts

从C过度到C++,总有些地方会不适应,比如cast。之前一直困惑,为什么有些程序会用xx_cast,明明括号就可以搞定的啊?读完这节,觉今是而昨非了。


1  什么C-Style和C++-Style cast?

C:(type) expression

C++:xxx_cast<type>(expression)


2  有什么区别? 

C:很粗鲁,几乎可以在任何类型间相互转换,它在提供便利的同时,也增加了很多不可控性,而后者是我们很忌惮的。另外,我们很难追踪cast在哪里被使用过。

C++:提供4种operators,精确控制4种类型的cast,比如static_cast并不能充当const_cast的角色。


3 C++ Cast Operators

i) static_cast

"static_cast has basically the same power and meaning as the general-purpose C-style cast. It also has the same kind of restrictions. For example, you can't cast a struct into an int or a double into a pointer using static_cast any more than you can with a C-style cast. Furthermore, static_cast can't remove constness from an expression, because another new cast, const_cast, is designed specifically to do that. "

static_cast就像多数的C类型映射,将一种数据类型转换成另一种,它也有同样的限制,比如不能将struct转换成int。另外,正如前面提到的,它也不能去除一个对象的const属性。


ii) const_cast

const_cast is used to cast away the constness or volatileness of an expression. By using a const_cast, you emphasize (to both humans and compilers) that the only thing you want to change through the cast is the constness or volatileness of something. This meaning is enforced by compilers. If you try to employ const_cast for anything other than modifying the constness or volatileness of an expression, your cast will be rejected.

const_cast只能用来去除对象的constness or volatileness,编译器看到这个关键字后就会知道使用者的明确意图。如果你想用const_cast来做其他类型映射的话,就YY了。

Example:

class Widget { ... };
class SpecialWidget: public Widget { ... };

void update(SpecialWidget *psw);

SpecialWidget sw;                                  // sw is a non-const object,
const SpecialWidget& csw = sw;          // but csw is a reference to
                                                              // it as a const object
                        
update(&csw);                                      // error! can't pass a const SpecialWidget* to a function taking a SpecialWidget*
                        
update(const_cast<SpecialWidget*>(&csw));                // fine, the constness of &csw is explicitly cast away (and csw — and sw — may now be
                                                                                       // changed inside update)
                        
update((SpecialWidget*)&csw);                                   // same as above, but using a
                                                                                     // harder-to-recognize C-style cast
                        
Widget *pw = new SpecialWidget;

update(pw);                                                                  // error! pw's type is Widget*, but update takes a SpecialWidget*

update(const_cast<SpecialWidget*>(pw));                 // error! const_cast can be used only  to affect constness or volatileness,
                                                                                     // never to cast down the inheritance hierarch


iii) dynamic_cast

The second specialized type of cast, dynamic_cast, is used to perform safe casts down or across an inheritance hierarchy. That is, you use dynamic_cast to cast pointers or references to base class objects into pointers or references to derived or sibling base class objects in such a way that you can determine whether the casts succeeded. Failed casts are indicated by a null pointer (when casting pointers) or an exception (when casting references):

dynamic_cast用于将父类指针转换成子类指针,并返回转换的结果。指针转换失败会返回NULL Pointer,引用转换失败会返回exception.

Example:

Widget *pw;
...
update(dynamic_cast<SpecialWidget*>(pw));                         // fine, passes to update a pointer to the SpecialWidget pw points to
                                                                                                  // if pw really points to one, otherwise passes the null pointer
void updateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw));           // fine, passes to updateViaRef the SpecialWidget pw points to if pw
                                                                                                 // really points to one, otherwise throws an exception


iv) reinterpret_cast

The last of the four new casting forms is reinterpret_cast. This operator is used to perform type conversions whose result is nearly always implementation-defined. As a result, reinterpret_casts are rarely portable.

我理解,这应该是可以用户自定义的类型转换操作符,所以它的可移植性不佳。最常用的功能是cast betwwen function pointer types。

Example:

typedef void (*FuncPtr)();         // a FuncPtr is a pointer to a function taking no args and returning void
FuncPtr funcPtrArray[10];          // funcPtrArray is an array of 10 FuncPtrs
int doSomething();

funcPtrArray[0] = &doSomething;                                                // error! type mismatch
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);   // this compiles


4 Different Compilers

某些编译器可能不支持这类cast operators,这时候为了保持程序的兼容性和一致性,可以定义一些宏来完成大致的功能。另外,我们可以方便地追踪cast的使用情况。


总结:

new cast operators虽然丑了点,但是作用突出。既能方便人类和工具解析它们的含义,又能方便编译器检测诊断casting errors。塞文失马,焉知非福?


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用 JavaScript 编写的杀死幽灵游戏(附源代码) 杀死鬼魂游戏是使用 Vanilla JavaScript、CSS 和 HTML 画布开发的简单项目。这款游戏很有趣。玩家必须触摸/杀死游荡的鬼魂才能得分。您必须将鼠标悬停在鬼魂上 - 尽量得分。鬼魂在眨眼间不断从一个地方移动到另一个地方。您必须在 1 分钟内尽可能多地杀死鬼魂。 游戏制作 这个游戏项目只是用 HTML 画布、CSS 和 JavaScript 编写的。说到这个游戏的特点,用户必须触摸/杀死游荡的幽灵才能得分。游戏会根据你杀死的幽灵数量来记录你的总分。你必须将鼠标悬停在幽灵上——尽量得分。你必须在 1 分钟内尽可能多地杀死幽灵。游戏还会显示最高排名分数,如果你成功击败它,该分数会在游戏结束屏幕上更新。 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox。要玩游戏,首先,单击 index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值