C ++显式转换真的那么糟糕吗?

时间:2010-06-15 13:33:16

标签: c++ casting

此时我对C ++的了解比其他任何事情都更具学术性。在我迄今为止的所有阅读中,使用带有命名演员表的显式转换(const_caststatic_castreinterpret_castdynamic_cast)都带有一个大警告标签(并且它是很容易理解为什么)这意味着明确的转换是不良设计的症状,应该只是在绝望的情况下作为最后的手段。所以,我不得不问:

使用命名演员表进行显式转换真的只是陪审团操纵代码还是这个功能有更优雅和积极的应用?后者有一个很好的例子吗?

6 个答案:

答案 0 :(得分:19)

有些情况下你不能没有它。像this one一样。问题在于您有多个继承并需要将this指针转换为void*,同时确保进入void*的指针仍将指向当前对象的右子对象。使用显式强制转换是实现这一目标的唯一方法。

有一种观点认为,如果你不能没有演员阵容你就会有糟糕的设计。我完全不同意这一点 - 不同的情况是可能的,包括上面提到的情况,但也许如果你需要经常使用显式演员,你真的有糟糕的设计。

答案 1 :(得分:11)

在某些情况下,您无法真正避免显式转换。特别是在与C库或设计糟糕的C ++库交互时(例如用作示例的COM库sharptooth)。

一般来说,使用显式演员表是一个红色的鲱鱼。它并不一定意味着代码不好,但确实会引起人们对潜在危险用途的关注。

但是你不应该将4个演员阵容扔在同一个包里:static_castdynamic_cast经常用于向上投射(从Base到Derived)或用于在相关类型之间导航。它们在代码中的出现非常正常(事实上,如果没有这样的话,很难编写Visitor模式。)

另一方面,const_castreinterpret_cast的使用更加危险。

  • 使用const_cast尝试修改只读对象是未定义的行为(感谢James McNellis进行更正)
  • reinterpret_cast通常仅用于处理原始内存(分配器)

当然,它们有它们的用途,但在普通代码中不应该遇到它们。对于处理外部或C API,它们可能是必要的。

至少这是我的意见。

答案 2 :(得分:6)

施法者的糟糕程度通常取决于施法类型。所有这些演员阵容都有合法用途,但有些人比其他演员更难闻。

const_cast用于抛弃const ness(因为添加它不需要强制转换)。理想情况下,永远不应该使用它。它可以很容易地调用未定义的行为(尝试更改最初指定的对象const),并且在任何情况下都会破坏程序的const - 正确性。有时需要与自身const不正确的API进行交互 - 这是正确的,例如,当他们要将char *视为const char *时,可能会要求reinterpret_cast,但是因为你不应该以这种方式编写API,这表明你使用的是一个非常旧的API或者某个人搞砸了。

int总是依赖于平台,因此在便携式代码中最有问题。此外,除非您对对象的物理结构进行低级操作,否则它不会保留意义。在C和C ++中,类型应该是有意义的。 int是一个意思是数字的数字;一个基本上是char s连接的dynamic_cast并不意味着什么。

Base *通常用于向下转换;例如从Derived *switch,附带条件是它工作或返回0.这颠覆OO的方式与类型标记上的static_cast语句大致相同:它移动了用于定义类远离类定义的代码。这将类定义与其他代码耦合在一起,增加了潜在的维护负担。

void *用于已知通常正确的数据转换,例如与void *之间的转换,类层次结构中已知的安全指针转换,这类事情。关于最坏的情况,你可以说它在某种程度上颠覆了类型系统。当与C库或标准库的C部分接口时,可能需要它,因为{{1}}经常用在C函数中。

一般来说,精心设计和编写良好的C ++代码将避免上述用例,在某些情况下,因为仅使用强制转换是为了做有潜在危险的事情,而在其他情况下,因为这样的代码往往会避免需要进行此类转换。 C ++类型系统通常被认为是一种维护的好东西,而强制转换它会破坏它。

答案 3 :(得分:3)

与大多数事情一样,IMO是工具,具有适当的用途和不适当的用途。转换可能是一个经常被不恰当地使用工具的区域,例如,在int和指针类型之间使用reinterpret_cast进行转换(可以在两个大小不同的平台上中断),或者到const_cast远离constness纯粹作为一个黑客,等等。

如果您知道它们的用途和用途,那么将它们用于它们的设计绝对没有错。

答案 4 :(得分:1)

对于明确的演员有讽刺意味。开发人员的C ++设计技巧很差,导致他编写需要大量演员的代码,他们是同一个开发人员,他没有适当地使用显式的编译机制,或者根本不使用C风格的编译器。

另一方面,了解其目的,何时使用以及何时不使用以及替代方案的开发人员不会编写需要大量投射的代码!


在boost转换库中查看这些转换的更细粒度的变体,例如polymorphic_cast,以便让您了解C ++程序员在转换时的谨慎程度。

答案 5 :(得分:1)

演员表示你正试图在一个方孔中放一个圆钉。有时这是工作的一部分。但是如果你对洞和钉子都有一些控制权,那么最好不要创造这个条件,写一个演员应该会引发你自己问自己是否有什么东西你可以这样做,这样会更顺畅。