C++函数式转换的目的究竟是什么?

Cpl*_*ent 26 c++ casting language-design

我说的是"类型(值)" - 样式演员.我读过的书很快就传递过来,只说它们在语义上等同于C风格的演员表,"(类型)值",并且应该避免它们.如果他们的意思与旧式演员的意思相同,他们为什么要加入这种语言呢?此外,因为声明可以包含多余的括号,所以此代码为:"T x(T(y));" 没有人打算使用函数式演员所期望的; 它声明了一个名为x的函数,它接受一个T并返回一个T而不是通过将y转换为T来构造一个名为x的T变量.

他们在语言设计上是个错误吗?

lee*_*777 25

函数样式转换为原始类型和用户定义类型带来了一致性.这在定义模板时非常有用.例如,采取这个非常愚蠢的例子:

template<typename T, typename U>
T silly_cast(U const &u) {
  return T(u);
}
Run Code Online (Sandbox Code Playgroud)

我的silly_cast函数适用于原始类型,因为它是一个函数式转换.它也适用于用户定义的类型,只要类T有一个带有U或U const&的参数构造函数.

template<typename T, typename U>
T silly_cast(U const &u) {
    return T(u);
}

class Foo {};
class Bar {
public:
    Bar(Foo const&) {};
};

int main() {
    long lg = 1L;
    Foo f;
    int v = silly_cast<int>(lg);
    Bar b = silly_cast<Bar>(f);
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎与模板中有用的相反.我会特别小心*避免在泛型编程中使用*C风格和函数风格的转换,因为例如你的`silly_cast`可以做任何C风格的演员可以做的事情,并且不清楚这是否是故意的. (2认同)
  • 在您的示例中,“Foo”可以隐式转换为“Bar”。而且由于“long”也可以隐式转换为“int”,因此根本不需要转换。另一方面,如果显式声明构造函数,则需要进行强制转换,但“static_cast”也可以使用,并且语法更简洁。 (2认同)
  • 您的示例似乎并未显示出T(x)的原因。您可以将模板写到`return(T)u;`,它是完全等效的。 (2认同)
  • 就像我说的,这是一个愚蠢的例子。重点是展示统一的符号:-) (2认同)

Joh*_*itb 13

它们的目的是让你可以将多个参数传递给类的构造函数:

T(a1, a2); // call 2-argument constructor
(T)(a1, a2); // would only pass a2.
Run Code Online (Sandbox Code Playgroud)

没有任何机制可以使(T) expr样式转换能够传递多个参数,因此需要一种新的转换形式.定义(T) expr为退化的情况是很自然的T(expr).

与这里的一些人所说的相反,(T) expr工作方式完全一样T(expr),所以它也适用于类类型.


Jon*_*ler 7

在一个已经大量(过度使用)括号的语言中解析函数式转换更容易一些.

他们是个错误吗?可能 - 但只是在他们无法完全取代C风格的演员表的程度上,因此提供了类似Perl的"有不止一种方法去做"演员的机制.凭借明确而独特的现代演员阵容:

dynamic_cast<type>(value);
reinterpret_cast<type>(value);
static_cast<type>(value);
const_cast<type>(value);
Run Code Online (Sandbox Code Playgroud)

没有理由再使用C风格的强制转换,也没有理由使用函数式转换.

  • @Matteo:我其实很喜欢.它有助于防止过度铸造,并使铸件像拇指一样伸出. (4认同)