什么是正确的用途?
(type)value
(类型)值type(value)
。如何决定在哪些具体情况下使用哪种方法?
static_cast
是你应该尝试使用的第一个转换。它可以做一些事情,如类型之间的隐式转换(如int
到float
,或指针到void*
),它也可以调用显式转换函数(或隐式的)。在许多情况下,明确说明static_cast
是没有必要的,但需要注意的是,T(something)
语法等同于(T)something
,应该避免使用(后面会详细介绍)。然而,T(something, something_else)
是安全的,并且保证调用构造函数。
static_cast
也可以通过继承层次结构进行投递。当向上投递时(投向基类),它是不必要的,但当向下投递时,只要不通过虚拟
继承投递,就可以使用。然而,它并不做检查,而且将 "static_cast "顺着层次结构投向一个实际上不是对象类型的类型,是未定义的行为。
const_cast
可以用来删除或添加const
到一个变量中;其他C++的cast都不能删除它(甚至reinterpret_cast
也不行)。需要注意的是,只有当原始变量是 "const "时,修改以前的 "const "值才是未定义的;如果你用它把 "const "从一个没有用 "const "声明的东西的引用中移除,那是安全的。例如,当基于const
重载成员函数时,这可能很有用。它也可以用来给一个对象添加`const',例如调用一个成员函数重载。
const_cast
在volatile
上也有类似的作用,不过这不太常见。
dynamic_cast
专门用于处理多态性。你可以将任何多态类型的指针或引用投向任何其他类的类型(一个多态类型至少有一个虚函数,声明或继承的)。你可以用它来做更多的事情,不仅仅是向下投递--你可以向侧面投递,甚至向另一个链上投递。dynamic_cast
将寻找所需的对象,如果可能的话将其返回。如果不能,它将在指针的情况下返回 "nullptr",或者在引用的情况下抛出 "std::bad_cast"。
dynamic_cast
有一些限制。如果在继承层次中有多个相同类型的对象(即所谓的 "可怕的钻石"),并且你没有使用 "虚拟 "继承,它就不起作用。它也只能通过公共继承--它总是不能通过 "受保护 "或 "私有 "的继承。不过,这很少是个问题,因为这种形式的继承很少见。
reinterpret_cast
是最危险的投射,应该非常谨慎地使用。它将一种类型直接转化为另一种类型--比如将一个指针的值转化为另一个指针的值,或者将一个指针存储在一个int'中,或者其他各种讨厌的事情。大体上,你用
reinterpret_cast得到的唯一保证是,通常如果你把结果投回原始类型,你会得到完全相同的值(但如果中间类型比原始类型小,则******不会)。有许多转换是**
reinterpret_cast`**不能做的。它主要用于特别奇怪的转换和位操作,比如把原始数据流变成实际的数据,或者把数据存储在指向对齐数据的指针的低位。
C-style cast和function-style cast是分别使用(type)object
或type(object)
进行的转换,在功能上是等同的。它们被定义为以下第一种成功的情况。
static_cast
(虽然忽略了访问限制)static_cast
(见上文),然后const_cast
。reinterpret_cast
,然后是const_cast
。因此,在某些情况下,它可以用来替代其他的投射,但由于能够演变成reinterpret_cast',所以会非常危险,当需要显式投射时,应该首选后者,除非你确定
static_cast'会成功或`reinterpret_cast'会失败。即使如此,也要考虑更长、更明确的选项。
在执行static_cast
时,C-style casts也忽略了访问控制,这意味着它们有能力执行其他cast不能执行的操作。但这主要是一种笨拙的做法,在我看来,这只是另一个避免C-style casts的理由。
使用dynamic_cast
来转换继承层次结构中的指针/引用。
使用static_cast
进行普通的类型转换。
使用reinterpret_cast
对比特模式进行低层次的重新解释。 使用时要特别小心。
使用const_cast
进行const/volatile
的转换。 避免这样做,除非你被困于使用常量不正确的API。