一尘不染

什么时候应该使用 static_cast、dynamic_cast、const_cast 和 reinterpret_cast?

c++

什么是正确的用途:

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast
  • C型演员表(type)value
  • 函数式强制转换type(value)

如何决定在哪些特定情况下使用哪个?


阅读 272

收藏
2022-01-26

共1个答案

一尘不染

static_cast是您应该尝试使用的第一个演员表。它执行诸如类型之间的隐式转换(例如inttofloat或指向 的指针void*)之类的事情,它还可以调用显式转换函数(或隐式转换函数)。在许多情况下,static_cast不需要显式声明,但重要的是要注意T(something)语法等效于(T)something并且应该避免(稍后会详细介绍)。然而, AT(something, something_else)是安全的,并保证调用构造函数。

static_cast也可以通过继承层次结构进行转换。向上转换(朝向基类)时没有必要,但向下转换时,只要不通过virtual继承进行转换,就可以使用它。但是,它不进行检查,并且将static_cast层次结构向下到实际上不是对象类型的类型是未定义的行为。


const_cast可用于删除或添加const到变量;没有其他 C++ 演员能够删除它(甚至没有reinterpret_cast)。需要注意的是,只有当原始变量是;时,修改以前的const值才是未定义的。const如果您使用它来取消对const未声明的内容的引用const,则它是安全的。例如,这在基于 重载成员函数时很有用const。它也可以用来添加const到一个对象中,比如调用一个成员函数的重载。

const_cast也同样适用于volatile,尽管这种情况不太常见。


dynamic_cast专门用于处理多态性。您可以将指向任何多态类型的指针或引用转换为任何其他类类型(多态类型至少有一个声明或继承的虚函数)。您不仅可以将其用于向下投射 - 您还可以向侧面投射,甚至可以向上投射另一条链。将dynamic_cast寻找所需的对象并在可能的情况下返回它。如果不能,它会nullptr在指针的情况下返回,或者在引用的情况下抛出std::bad_cast

dynamic_cast但是有一些限制。virtual如果继承层次结构中有多个相同类型的对象(所谓的“可怕的菱形”)并且您没有使用继承,则它不起作用。它也只能通过公共继承——它总是无法通过protectedprivate继承。然而,这很少成为问题,因为这种继承形式很少见。


reinterpret_cast*是最危险的演员表,应该非常谨慎地使用。它将一种类型直接转换为另一种类型——例如将值从一个指针转换为另一个指针,或将指针存储在 中int,或各种其他讨厌的事情。很大程度上,您获得的唯一保证reinterpret_cast是,通常如果您将结果转换回原始类型,您将获得完全相同的值(但如果中间类型小于原始类型,则不会)。*也有许多reinterpret_cast**不能做的转换。它主要用于特别奇怪的转换和位操作,例如将原始数据流转换为实际数据,或将数据存储在指向对齐数据的指针的低位中。


C 风格转换和函数风格转换分别使用(type)objector进行转换type(object),并且在功能上是等价的。它们被定义为以下成功的第一个:

  • const_cast
  • static_cast(虽然忽略了访问限制)
  • static_cast(见上文),然后const_cast
  • reinterpret_cast
  • reinterpret_cast, 然后const_cast

因此,在某些情况下,它可以用作其他类型转换的替代品,但由于能够演变为 a reinterpret_cast,因此可能非常危险,并且在需要显式转换时应首选后者,除非您确定static_cast会成功或reinterpret_cast会失败. 即便如此,考虑更长、更明确的选项。

C 风格的强制转换在执行 a 时也会忽略访问控制static_cast,这意味着它们能够执行其他强制转换无法执行的操作。不过,这主要是一个杂物,在我看来,这只是避免 C 风格转换的另一个原因。

2022-01-26