我理解(MyType)foo
,MyType(foo)
和static_cast<MyType>(foo)
有些相似,因为前两个成为最后一个(编辑:我已被纠正。前一句话是不真实的。)我的问题是哪个是惯用版?背景是一个考虑因素吗?
因为我知道在C ++中不喜欢C样式转换,所以它取决于功能转换和static_cast。
答案 0 :(得分:3)
在我的书中使用显式演员是惯用的。
static_cast<MyType>(foo)
优于(MyType)foo
,因为它更具表现力和表达能力。这在(MyType)foo
不意味着它意味着什么的许多情况下尤其有用。例如,在您的示例中,这些案例可能根本不会减少到static_cast
,而是reinterpret_cast
。
在代码审查中,我会拒绝非算术类型的所有C风格的演员表。
答案 1 :(得分:2)
首先,虽然是C ++的新手,但功能样式转换是 C风格的转换。他们做同样的事情。
C风格演员表首先尝试static_cast
,如果这不起作用,reinterpret_cast
1 。这很糟糕,因为旨在进行简单更改的操作可能会变得非常奇怪。
例如,假设您有一个Foo* f
和一个完全不相关的类Bar
。您可以(Bar*)f
,它会默默地将*f
重新解释为Bar
,可能会导致未定义的行为。
如果static_cast
和Foo
是相关类型,则Bar
仅适用于此情况。
现在,即使static_cast
也可能过于强大,因此我经常会编写一个implicit_cast
或non_cast
模板来转换 - 无需转换。同样,我写as_const
添加const
而不是const_cast
(可以添加和删除const
,删除const
远比explicit
更危险。加上它。)
在C ++中没有明确的安全强制转换有点烦人,我不知道如何编写一个(一个将执行static_cast
构造函数,但不会强制转换#34; down&#34;像{{1}}这样的类型层次结构。)
1 这是一种过度简化,但足够接近真实。
答案 2 :(得分:2)
前两个(MyType)foo
和MyType(foo)
具有相同的含义。意义的含义在很大程度上取决于MyType
和foo
的类型。例如:
((int)1.0); // a static_cast
int i = 0;
((char*)&i); // a reinterpret_cast
const int j = 0;
((int*)&j); // a const_cast
((char*)&j); // a combination of a const_cast and a reinterpret_cast
typedef char *CharPtr;
CharPtr(&j); // a C-style cast, same as ((CharPtr)&j) or ((char*)&j)
因此,C风格的演员表不是首选的原因是C风格演员阵容做了很多不同的事情。 C ++提供了区分它们的方法。在很多情况下,这样可以更容易理解代码,特别是在用C ++编写通用代码之后,类型不像C语言那样明显。
这就是为什么static_cast
等在C ++中首选的原因 - 它们为读者明确规定了一些可能难以为自己解决的问题。顺便说一句,static_cast
也做了一些不同的事情,所以原则上你可能想要更多不同的演员阵容。但是static_cast
至少比C风格的演员要少。
带有一个参数的功能样式转换是 C风格的转换。在所有情况下,它们在标准中明确定义为完全相同的东西。
现在,在某些情况下,您可以在使用函数语法编写时接受C样式转换,但在使用C转换语法编写时则不行。这通常是在目标类型是一个类时,很明显将调用哪个构造函数。在这种情况下,std::vector<int>(0)
比static_cast<std::vector<int>>(0)
短,并且通常更清晰,因为它可以被读作构造函数调用。但它仍然具有与写(std::vector<int>)0
相同的“危险”。如果您以这种方式编写每个转换,那么最终您会不小心从指针类型中删除const
。