我听说该static_cast
函数应该优先于C风格或简单的函数式转换.这是真的?为什么?
主要的原因是,经典的C蒙上之间做出我们所说的没有什么区别static_cast<>()
,reinterpret_cast<>()
,const_cast<>()
,和dynamic_cast<>()
.这四件事完全不同.
A static_cast<>()
通常是安全的.语言中有一个有效的转换,或者使它成为可能的适当构造函数.唯一一次有点危险的是当你被归入一个继承的阶级时; 您必须通过语言外部的方式(如对象中的标志)确保该对象实际上是您声称它的后代.dynamic_cast<>()
只要检查结果(指针)或考虑可能的异常(参考),A 就是安全的.
另一方面,A reinterpret_cast<>()
(或a const_cast<>()
)总是危险的.你告诉编译器:"相信我:我知道这看起来不像foo
(看起来好像它不可变),但它是".
第一个问题是,几乎不可能在没有大量分散代码和了解所有规则的情况下分辨C风格的演员阵容.
我们假设这些:
class CDerivedClass : public CMyBase {...}; class CMyOtherStuff {...} ; CMyBase *pSomething; // filled somewhere
现在,这两个编译方式相同:
CDerivedClass *pMyObject; pMyObject = static_cast(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(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(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风格的演员阵容更加危险,而且要找到它们以确保它们是正确的更难.
一个实用的提示:如果您打算整理项目,可以在源代码中轻松搜索static_cast关键字.
简而言之:
static_cast<>()
给你一个编译时检查能力,C-Style演员没有.
static_cast<>()
可以在C++源代码中的任何地方轻松发现; 相比之下,C_Style演员更难以发现.使用C++强制转换可以更好地传达意图.
更多说明:
静态强制转换执行兼容类型之间的转换.它类似于C风格的演员表,但更具限制性.例如,C样式转换将允许整数指针指向char.
char c = 10; // 1 byte int *p = (int*)&c; // 4 bytes由于这会导致4字节指针指向已分配内存的1个字节,因此写入此指针将导致运行时错误或将覆盖某些相邻内存.
*p = 5; // run-time error: stack corruption与C样式转换相反,静态转换将允许编译器检查指针和指针数据类型是否兼容,这允许程序员在编译期间捕获这种不正确的指针赋值.
int *q = static_cast(&c); // compile-time error
阅读更多内容:
static_cast <>和C样式转换
以及Regular cast与static_cast与dynamic_cast 之间的区别是什么
问题不仅仅是使用枯萎的static_cast或C样式转换,因为使用C样式转换时会发生不同的事情.C++强制转换操作符旨在使这些操作更加明确.
表面上,static_cast和C样式转换看起来是一样的,例如在将一个值转换为另一个时:
int i; double d = (double)i; //C-style cast double d2 = static_cast( i ); //C++ cast
这两个都将整数值转换为double.然而,当使用指针时,事情变得更加复杂.一些例子:
class A {}; class B : public A {}; A* a = new B; B* b = (B*)a; //(1) what is this supposed to do? char* c = (char*)new int( 5 ); //(2) that weird? char* c1 = static_cast( new int( 5 ) ); //(3) compile time error
在这个例子中(1)也许没问题,因为A指向的对象实际上是B的一个实例.但是如果你在代码中不知道实际指向的是什么呢?(2)也许完全合法(你只想查看整数的一个字节),但它也可能是一个错误,在这种情况下错误会很好,如(3).C++转换运算符旨在通过在可能的情况下提供编译时或运行时错误来在代码中公开这些问题.
因此,对于严格的"值转换",您可以使用static_cast.如果要运行时多态转换指针,请使用dynamic_cast.如果您真的想忘记类型,可以使用reintrepret_cast.只是将const抛出窗口就有const_cast.
它们只是使代码更加清晰,因此看起来你知道自己在做什么.
static_cast
意味着你不能意外const_cast
或者reinterpret_cast
,这是一件好事.
这是关于你想要施加多少类型安全性.
当你写(bar) foo
(这相当于reinterpret_cast
你没有提供类型转换操作符)时,你告诉编译器忽略类型安全,并按照它的说法去做.
在编写时,static_cast
您要求编译器至少检查类型转换是否有意义,对于整数类型,请插入一些转换代码.
编辑2014-02-26
我在5年多前写过这个答案,我弄错了.(见评论.)但它仍然得到了支持!
允许使用grep或类似工具在代码中轻松找到强制转换.
明确表示您正在做什么样的演员表,并让编译器帮助他们执行.如果你只想抛弃const-ness,那么你可以使用const_cast,它不允许你进行其他类型的转换.
转换本质上是丑陋的 - 你作为程序员正在推翻编译器通常如何处理你的代码.你是对编译器说的,"我比你更清楚." 在这种情况下,执行演员应该是一件中等难度的事情是有道理的,并且他们应该在你的代码中坚持下去,因为它们可能是问题的根源.
请参阅有效的C++简介
C样式强制转换很容易在代码块中丢失。C ++样式转换不仅是更好的做法,它们提供了更大的灵活性。
reinterpret_cast允许整数到指针类型的转换,但是如果使用不当,可能是不安全的。
static_cast为数字类型提供了良好的转换,例如从枚举到int或从ints到float或您确信类型的任何数据类型。它不执行任何运行时检查。
另一方面,dynamic_cast将执行这些检查,标记所有不明确的分配或转换。它仅适用于指针和引用,并且会产生开销。
还有其他一些,但是这些是您会遇到的主要问题。