type(myVar)和(type)myVar有什么区别?(涉及IT技术)

18

我正在按照cplusplus.com上的完整教程,手动编写和编译每个示例。经常会遇到令我困惑的问题。

目前我正在学习这个部分:http://www.cplusplus.com/doc/tutorial/structures/。有些微妙之处可能只是在阅读教程时被忽略了。手工输入每个字符的好处在于此类细节确实会引起注意。

在上述页面中,有两个示例程序。其中一个有以下这行代码:

stringstream(mystr) >> yours.year;
另一个代码片段包含以下行:

The other one has this line:

(stringstream) mystr >> pmovie->year;

我不明白type (myVar) = x;(type) myVar = x;的区别(如果有的话)。

我没有按照顺序完成整个教程。 我检查过,但没有在任何地方找到解答,尽管我可能错过了。

  • 它们之间有什么区别吗?
  • 是否有一种更优选的方式?

12
这不是一个函数而是一个类。第一次调用是构造函数调用,第二次是类型转换运算符的调用。 - KeatsPeeks
2个回答

59

type(x)(type)x之间没有区别。这两者完全等效。大多数人更喜欢在类中使用type(x),在非类类型中使用(type)x,但这纯粹取决于个人选择。两者都将带有一个参数x调用类的构造函数。

类的首选方式是type(x),因为这允许向构造函数传递多个参数,例如type(x, y)。尝试使用另一种形式(type)x, y将无法工作:它会将x强制转换,然后应用逗号运算符并独立评估y。括号(type)(x, y)是没有帮助的:这将使用逗号运算符独立计算xy,然后将y转换为type

对于非类类型,这样的强制转换通常过于强大。C++具有static_cast<type>(x),可以粗略地执行隐式转换(例如将基类强制转换为派生类和将void*强制转换为另一个指针),这通常是适合的。请参阅When should static_cast, dynamic_cast and reinterpret_cast be used?

stringstream不是函数。执行function(x)将调用该函数,但执行(function)x是非法的,因为两个表达式相邻,中间没有运算符。


对于那些不相信此答案并基于直觉下投票的人,请在标准中查看5.2.3 / 1

简单类型说明符(7.1.5)后跟括号表达式列表,根据表达式列表构造指定类型的值。如果表达式列表是单个表达式,则类型转换表达式在定义性和(如果定义了含义)相应的强制类型转换表达式(5.4)中等效。


2
@nico 这不是一个观点问题。标准定义了什么是等效的,什么不是。它将这两者定义为等价的,因此编码风格要说在哪种情况下使用什么。 - Johannes Schaub - litb
5
这不属于神经科学领域:这些问题都已被一个标准明确规定,人们对语言的看法并不影响其语义。显然,您已经对此问题下定了决心,这很遗憾,但我不想改变它。我有更好的时间安排 :) - Johannes Schaub - litb
2
@nico 哦,我只是开玩笑。今天是星期天,该玩乐一下了。但说真的,标准规定两件事情是等价的 - 我认为这是一个明确的陈述。我没有看到它有任何解释的余地。如果您能展示一个清晰地表明这两种形式行为不同的代码示例,我会很高兴的。我认为我同意它们在词法上是不同的,就像150xf是“不同”的一样,但这有什么关系呢?你完全可以自己选择是用十进制还是十六进制来输入。 - Johannes Schaub - litb
3
我想要表达的是,这两种操作都是转换,尽管如此。它们都调用类的构造函数,而不是非类的构造函数。你可以说int(some_pointer)或(int)some_pointer。我认为没有必要说其中一种形式会调用构造函数,而另一种形式则是强制类型转换,因为这暗示了一个不存在的差异。在int(some_pointer)中没有构造函数的调用。我可以称10为十进制数的“创建”,称0x10为其“转换”,因为它看起来很可爱,但这并不改变任何关于其语义的东西。这完全是主观的。 - Johannes Schaub - litb
13
谁特么的对这个回答点了踩? - GManNickG
显示剩余11条评论

4
你引用的网页并不是我认为关于C++的权威资料。无论如何,`(stringstream) mystr >> pmovie->year;`将一个`std::string`强制转换为一个`std::stringstream`对象。这是一种C风格的转换方式。如果你不知道自己在做什么,那么这种方式会非常危险。接下来,该值被提取到了`pmovie->year`中。
`stringstream(mystr) >> yours.year;`创建了一个匿名的`std::stringstream`对象,并使用`mystr`对其进行初始化,然后将该值提取到`pmovie->year`中。该对象在其词法作用域结束时消失,而在本例中,这个作用域是行末的分号。
就类对象而言,两种方式之间没有太大区别(正如其他人到目前为止所指出的那样)。
另一方面,对于标识符(函数/宏),这就变得棘手了:`function(myVar) = x;`无论`function`是实际的函数还是宏,都可以正常工作。然而,`(function)(myVar) = x;`只适用于真正的函数。
某些标准库标识符允许同时具有两种形式(最明显的是`tolower`和相关函数),因此,如果您想始终调用函数,则应该选择前者。

1
cplusplus.com出了什么问题吗?我经常使用他们的参考资料。 - rubenvb
1
这当然是个人观点。而且OP的问题就是一个很好的例子。 - dirkgently
1
你的回答表明这两种形式之间存在差异,但没有详细说明这种差异。它还暗示了不规范的表达式 (function) myVar 是有效的(而不是 (function)(myVar))。 - Johannes Schaub - litb
谢谢回复。我很高兴我问了。现在我理解得更好了。关于cplusplus.com:你会推荐哪个在线C++教程替代品?我刚刚发现http://www.learncpp.com/,它似乎更完整。我还使用cplusplus.com的std库参考:http://www.cplusplus.com/reference/。如果你知道更好的C++ std库参考网站,请告诉我。 - augustin
2
作为参考:我更喜欢SGI STL网站和MSDN参考(尽管有时示例非常丑陋)。尝试一本书(比如Stroustrup写的)通常被认为是一个不错的开始。 - dirkgently

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接