C样式转换或C ++样式转换


21

那么,您使用什么呢?

int anInt = (int)aFloat;

要么

int anInt = static_cast<int>(aFloat);
// and its brethren

而且,更重要的是,为什么?

Answers:


45

首先,请了解这些行并不等效

int* anInt = (int*)aFloat; // is equivalent to

int* anInt = reinterpret_cast<int*>(aFloat); 

这里发生的是程序员正在要求编译器尽一切可能进行转换。

区别很重要,因为使用static_cast只会要求将“安全”的基本类型转换为,而reinterpret_cast将转换为任何类型的基本类型,可能只是将所需的内存布局映射到给定对象的内存上。

因此,由于“过滤器”不同,因此如果您依赖编译器(或者如果使用dynamic_cast则是运行时隐含的)来告诉您在哪里做错了,则使用特定的类型转换比使用C类型的转换更加清晰和安全。 ,请避免C强制转换和reinterepret_cast。

既然更清楚了,那么还有另一件事:static_cast,reinterpret_cast,const_cast和dynamic_cast 更易于搜索

最终点:它们丑陋。想要的。潜在的错误代码,代码气味,明显的“技巧”(可能会产生错误)在与丑陋外观关联时更易于跟踪。错误的代码应该难看

那是“设计使然”。这样开发人员就可以知道自己可以做得更好的地方(如果不需要,可以完全避免强制转换),哪里还可以,但是通过“标记”为丑陋的方式将其记录在代码中。

引入新型强制转换的第二个原因是C强制转换很难在程序中发现。例如,您无法使用普通的编辑器或文字处理器方便地搜索演员表。C型演员表的这种近乎隐形的情况尤其不幸,因为它们具有潜在的破坏性。丑陋的操作应具有丑陋的句法形式。该观察结果是为新型演员表选择语法的部分原因。另一个原因是新型强制转换必须与模板符号匹配,以便程序员可以编写自己的强制转换,尤其是运行时检查的强制转换。

也许是因为static_cast太丑陋且很难键入,所以您更可能在使用它之前三思而后行?那会很好,因为在现代C ++中,强制转换实际上是可以避免的。

资料来源:Bjarne Stroustrup(C ++创建者)


2
如果我还有其他几点,我会投票反对,但不幸的是我不能。C样式转换不等同于reinterpret_cast。考虑一下reinterpret_cast<int>(double);。完全可以使用c样式强制转换将双精度类型转换为int,但是使用reinterpret_cast则不可能。我看到Timbo已经向您指出了这一点,您说过要修复它,但是四年后仍然不正确。如果已解决问题,我仍然会投票反对,因为完全有正当理由需要使用演员表。这是一个更好的答案:stackoverflow.com/a/332086/3878168
Yay295

36

C ++强制转换更具限制性(因此,可以更好地表达您的意图,并简化代码审查等)。如果需要,它们也更容易搜索。


10
...,他们更有可能按照您的意愿去做。;-)
Macke

7
而且它们还有很多输入的类型,这为您提供了一个无需更改强制转换即可正确输入正确类型的理由。
Michael Kohne

7
而且它们的功能很丑陋,很明显在代码中可能需要改进的地方或特殊情况需要文档。-编辑:哇,我刚刚发现我也回答了这个问题!XD
Klaim 2011年

现在为什么要搜索它们?
Deduplicator 2015年

@Deduplicator有很多原因,您可能想知道代码库中强制转换的位置。例如,在寻找可能与转换相关的错误时(尤其是在进行跨平台开发时)。
Klaim 2015年

13

选项C:“ C ++样式”的强制类型转换,因为它与构造没有区别:

int anInt = int(aFloat);

甚至:

int anInt(aFloat);

除此之外,除了这些众所周知的琐碎琐事之外,我更喜欢使用x_cast <> s而不是C样式的强制类型转换。原因有以下三个:

  • 它们更狭义地定义了程序员试图执行的操作。

  • 他们可以执行C样式强制转换无法执行的操作(特别是对于dynamic_cast <>而言,它可以跨多继承链的分支进行交叉转换)。

  • 他们很丑。他们大声宣布程序员正在对类型系统进行操作。在这种情况下,这是一个很好的事情。


7

如果用C编写代码,请使用C强制转换。如果使用C ++编写,请使用C ++强制转换。

尽管大多数强制转换会破坏适当的类型安全性,但C ++的安全性更严格,因此与C强制转换相比,类型不安全性要少一些。

我可以容忍使用(T *)NULL的人,尽管可以强制过载。


7

关于C / C ++样式的强制转换,我有一些规则:

  1. 取消使用const必须始终使用const_cast。出于明显的原因。不幸的是,我关于取消使用const导致键盘伸出并打断程序员手指的规则未获批准。
  2. 程序员在接触到金属时所使用的任何位操纵样式的恶作剧都应该使用reinterpret_cast。这确实是C所没有的强制类型转换:假设此整数的位实际上是浮点数的位。这样可以避免类似的不愉快行为(int)(*(int*)(&floatVar))
  3. 如果键入单词“ dynamic_cast”,请停止并重新评估您的多态类层次结构和设计。继续重新评估类层次结构的设计,直到您可以删除这些单词。
  4. 不用理会static_cast

#4背后的理由很简单,那就没关系。不适合其他规则的情况是显而易见的,或者是非常低级的。易于理解的简单类型(如int到float)的转换不需要特殊的语法。而且,如果您陷入某物的深沉,丑陋的胆量中,那么,您就会陷入某物的深沉,丑陋的胆量中。无需引起注意“这里有龙”这一事实,因为牙齿,爪子和火几乎已经把它放走了。


1
dynamic_cast是一个非常有效的工具。我承认,它很少有用,但是它与诸如全局变量之类的撒旦相去甚远。然而,主要是,我downvoted你,因为你没有回答这个问题,这是关于C风格的类型转换的使用与否。
DeadMG 2011年

2
@DeadMG:我确实谈到了C风格的类型转换。整个最后一段证明C样式强制转换支持static_cast。
Nicol Bolas

“不幸的是,我关于取消使用const导致键盘伸出并打断程序员手指的规则未获批准。” 从技术上讲,使编译器实现该目标实际上是合法的。编译器让恶魔从你的鼻子里飞出来是合法的。
法老


3

这实际上取决于我使用的是哪种语言,因为您知道他们说的是什么:在罗马说罗马。因此,如果我使用C进行编程,我会尽量使用C功能,但是如果我使用C ++进行编程,那么我会继续使用C ++功能,即使有些人不喜欢这种方法,因为他们说这使代码“不太容易移植”,我说我不在乎,我使用C ++和C ++进行编程,并且我需要一个完全与C ++兼容的编译器来编译代码,否则我将使用其他不同的东西首先。


在C ;-)中尝试使用C ++样式的强制转换真的不起作用;
Steve314 2011年

3

由于在模板中使用C样式转换时出现了问题,因此发明了static_cast等。如果您正在编写模板,或者您的代码以后可能会转换为模板,则使用C ++样式的强制转换是一个好主意。原因是因为C ++样式转换更好地表达了意图,所以在C样式转换将执行错误的操作(给定特定类型的模板参数)的情况下,它们将提供预期的结果。

除此之外,我说如果您有一个特定的问题需要C ++样式的强制转换-dynamic_cast是最常见的,但是即使那样也不是每天都会发生的。

除此以外,C风格的转换可能会稍微混乱一些,并有助于提高可读性,或者也许不取决于当今读者对这种转换样式的熟悉程度。在我看来,这并不是很重要,主要是个人喜好,尽管有些人不喜欢C风格也不要感到惊讶。

最后说明-如果您需要大量转换,这很重要,那么您可能在做其他错误。在某些情况下,有一些例外,但是大多数高级代码不需要太多(如果有的话)强制类型转换。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.