我据说static_cast
函数应该比C样式或简单的函数样式转换更可取。 这是真的? 为何? 前端
除处理指向类的指针外,static_cast还能够用于执行在类中显式定义的转换,以及在基本类型之间执行标准转换: 安全
double d = 3.14159265; int i = static_cast<int>(d);
static_cast
意味着您不能偶然const_cast
或reinterpret_cast
,这是一件好事。 函数
这是关于您要强加多少类型安全性。 工具
当您编写(bar) foo
(若是您未提供类型转换运算符,则至关于reinterpret_cast<bar> foo
),您是在告诉编译器忽略类型安全性,并按照提示执行操做。 spa
在编写static_cast<bar> foo
您要求编译器至少检查类型转换是否有意义,对于整数类型,请插入一些转换代码。 指针
编辑2014-02-26 code
我在5年前就写了这个答案,但我弄错了。 (请参阅评论。)可是它仍然会被投票! 对象
一个实用的技巧:若是您打算整理项目,则能够在源代码中轻松搜索static_cast关键字。 继承
主要缘由是经典C强制转换在咱们称为static_cast<>()
, reinterpret_cast<>()
, const_cast<>()
和dynamic_cast<>()
之间没有区别。 这四件事彻底不一样。 编译器
static_cast<>()
一般是安全的。 语言存在有效的转换,或者使之成为可能的适当的构造函数。 惟一有风险的是当您降级为继承的类时。 您必须经过语言外部的方式(例如对象中的标记)确保该对象其实是您声称的对象的后代。 只要检查结果(指针)或考虑到可能的异常(引用), dynamic_cast<>()
都是安全的。
另外一方面, reinterpret_cast<>()
(或const_cast<>()
)始终很危险。 您告诉编译器:“相信我:我知道这看起来不像foo
(看起来好像是不可变的),可是确实如此。”
第一个问题是,在不查看大量分散代码并知道全部规则的状况下,几乎不可能分辨出将在C样式转换中发生哪个。
让咱们假设这些:
class CDerivedClass : public CMyBase {...}; class CMyOtherStuff {...} ; CMyBase *pSomething; // filled somewhere
如今,这两种编译方式相同:
CDerivedClass *pMyObject; pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<> // Safe; as long as we checked // but harder to read
可是,让咱们看一下几乎相同的代码:
CMyOtherStuff *pOther; pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert pOther = (CMyOtherStuff*)(pSomething); // No compiler error. // Same as reinterpret_cast<> // and it's wrong!!!
如您所见,在不了解全部涉及的全部类的状况下,没有简单的方法来区分这两种状况。
第二个问题是C样式转换很难定位。 在复杂的表达式中,很难看到C样式的强制转换。 在没有完整的C ++编译器前端的状况下,几乎不可能编写须要定位C样式转换的自动化工具(例如搜索工具)。 另外一方面,很容易搜索“ static_cast <”或“ reinterpret_cast <”。
pOther = reinterpret_cast<CMyOtherStuff*>(pSomething); // No compiler error. // but the presence of a reinterpret_cast<> is // like a Siren with Red Flashing Lights in your code. // The mere typing of it should cause you to feel VERY uncomfortable.
这意味着,不只C风格的强制转换更加危险,并且要确保它们正确无误地查找它们要困可贵多。