简体   繁体   English

函数式演员被视为有害吗?

[英]Function-style casts considered harmful?

I understand that generally C-style casts are considered harmful. 据我所知,通常C风格的演员阵容被认为是有害的。 So, given a class Widget 所以,给出一个类Widget

class Widget{
public:
  explicit Widget(Gizmo gizmo);
};

I could call a function like this: 我可以调用这样的函数:

functionThatTakesAWidget((Widget) gizmo);

using a C-style cast. 使用C风格的演员。 Or I could write it using a function-style cast: 或者我可以使用函数式转换来编写它:

functionThatTakesAWidget(Widget(gizmo));

but this is exactly equivalent. 但这完全相同。 So no better or worse. 所以没有更好或更糟。 And If I really wanted to avoid a C-style cast I could write: 如果我真的想避免使用C风格的演员,我可以写:

functionThatTakesAWidget(static_cast<Widget>(gizmo));

But given a class Doohickey : 但是给了一个Doohickey类:

class Doohickey {
public:
  Doohickey(Gizmo left_gizmo, Gizmo right_gizmo);
};

I can't avoid writing: 我无法避免写作:

functionThatTakesADoohickey(Doohickey(left_gizmo, right_gizmo));

I assume this is not considered a 'cast' at all? 我认为这根本不算是“演员”? But what is the difference between this and a function-style cast? 但是这与功能风格的演员之间有什么区别? Why is this OK but a function-style cast is not? 为什么这样可以,但功能风格的演员表不是?

The reasons for avoiding C-Style casts are: 避免C-Style演员表的原因是:

  • Being explicit about what kind of casting happens, thus making sure no other type actually does. 明确发生什么样的铸造,从而确保没有其他类型实际发生。
  • Making casts easier findable. 使演员阵容更容易找到。

While the function-style cast looks safer, it's actually a C-style cast in disguise, so it does not really add anything. 虽然功能风格的演员看起来更安全,但它实际上是伪装的C风格演员,所以它并没有真正添加任何东西。

The driving reason behind being explicit is letting the compiler assert your assumptions, instead of silently doing (sometimes) the wrong thing. 明确的驱动原因是让编译器断言你的假设,而不是默默地做(有时)错误的事情。
IMHO, some purists go to far in their zeal though. 恕我直言,一些纯粹主义者在他们的热情中走得很远。

I wouldn't call Widget(gizmo) a "C-style cast". 我不会把Widget(gizmo)称为“C风格演员”。 In C you can't cast to a struct type anyway. 在C中,无论如何都不能转换为结构类型。 The main problem with "C-style casts" is when a pointer or reference cast is happening. “C风格演员表”的主要问题是当指针或参考演员发生时。 Then the C-style cast can be ambiguous or cause undefined behaviour. 然后,C风格的强制转换可能不明确或导致未定义的行为。

A value conversion is a different concept to a reference cast, in my view, and you don't need to use the same conventions for both. 在我看来,值转换是与引用转换不同的概念,并且您不需要对两者使用相同的约定。

The code is creating a temporary Widget , passing gizmo to the constructor. 代码正在创建一个临时Widget ,将gizmo传递给构造函数。 I think the static_cast version is misleading, and the Widget(gizmo) is fine. 我认为static_cast版本具有误导性, Widget(gizmo)很好。

BTW you could make functionThatTakesADoohickey overloaded to take a Gizmo , or a std::initializer_list<Gizmo> . 顺便说一句,你可以使functionThatTakesADoohickey重载以获取Gizmostd::initializer_list<Gizmo>

I believe: 我相信:

C c;
(A)c

calls the casting operator "C::operator A ()". 调用转换运算符“C :: operator A()”。 Which may be called when a C is provided, but an A is required. 当提供C时可以调用,但是需要A。 For example: 例如:

void f(A const&) { ... }
f(c);

Also, 也,

A(c)

calls the constructor: "A::A(const& C)". 调用构造函数:“A :: A(const&C)”。

I believe that if you don't define the cast operator, C++ may end calling the constructor implicitly to get the A. Sometimes this is a big disaster (let's say this constructor formats your hard drive and files for a divorce). 我相信如果你没有定义强制转换操作符,C ++可能会隐式调用构造函数来获取A.有时这是一个大灾难(假设这个构造函数格式化你的硬盘驱动器和文件离婚)。 So there's two remedies: 所以有两种补救措施:

class A {
public:
   explicit A(const& C);  // Don't call this when asking to cast to an A.
}

and also 并且

static_cast<A>(C);  // Really, just call the casting operator, don't implicitly cast.

Because "function-style" casts may file for divorce (by calling the constructor), they're considered harmful. 因为“函数式”强制转换可以提交离婚(通过调用构造函数),它们被认为是有害的。

There's nothing wrong with: 没有错:

f(c1,c1)

to get a A. People typically wouldn't think of it as a 'cast' which usually means 'turn this type of object into that type'. 获得A.人们通常不会将其视为“演员”,通常意味着“将此类对象转变为该类型”。

Typically you wouldn't write: 通常你不会写:

void AA(const& C) {...} // function void AA(const&C){...} //函数

to get 要得到

d = A(c) d = A(c)

because its confusing. 因为它令人困惑。 (is A class or a function?) (是一个类还是一个函数?)

And you'd prefer not to write: 你不想写:

void A toA(const& C) {...} void A toA(const&C){...}

simply because this functionality is better off encapsulated in the A class. 只是因为这个功能最好封装在A类中。 But its not otherwise particularly harmful. 但它不是特别有害。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM