我的老师不像其他人那样进行类型转换。有谁知道他在做什么?

My teacher is not type-casting the same way as everyone else. Does anyone know what he is doing?

我的老师在我们的一个铸造示例中包含了以下几行。 c 是 class Circle 的对象,它继承自 class Point。在寻找 "Can I cast an object of class Point to type Circle?" 问题的答案时,我发现他使用的语法与我访问过的每个网站都不同。这些网站都使用 static_castdynamic_cast 语法。他不会在测试中使用 static_cast 和 dynamic_cast,我只是想知道他在使用什么以及它是如何运作的。

此外,如果您能回答我是否可以将基对象转换为派生类型,我将非常感谢您。

output << "the center of the circle is at " << (Point) c; 
// casting `Circle` object `c` with type `(Point)`, calls the first overloaded >stream insertion operator"

这是一个 C 风格的转换,如果可用,将使用 "c.operator Point()",否则它的行为与 "reintrepret_cast(c)"

相同

(Point)c 被称为“C 风格”演员表。这基本上可以被认为是一种蛮力转换,它会尽其所能使转换成功。这意味着它最终可能导致 static_castconst_cast 甚至 reinterpret_cast.

When the C-style cast expression is encountered, the compiler attempts to interpret it as the following cast expressions, in this order:

  • const_cast
  • static_cast
  • static_cast 后跟 const_cast
  • reinterpret_cast
  • reinterpret_cast 后跟 const_cast

来源:https://en.cppreference.com/w/cpp/language/explicit_cast

来自 Stroustrup 本人:

Explicit type conversions (often called casts to remind you that they are used to prop up something broken) are best avoided.

C-style casts should have been deprecated in favor of named casts.

Stroustrup, Bjarne。 C++ 之旅(C++ 深入系列)(Kindle 位置 7134)。培生教育。 Kindle 版。

所以推荐命名转换。在实践中,我仍然会遇到使用 C 风格转换的专业代码,因为它使代码更简洁和可读,并且——如果你知道你在做什么——通常在它使用的地方等同于 static_cast。对于它的价值,我认为如果出于这些原因在使它 明显 的上下文中使用 C 样式转换是可以的,它将导致 static_cast,并且 Stroustrup 即将到来从过度面向对象的角度来看,他对演员表普遍不屑一顾。但是你应该更喜欢命名转换。

您的老师可能正在使用 C 风格的转换作为一种看起来不那么可怕的转换介绍。

到目前为止的答案并未涵盖 (Point) c; 的实际作用。假设 Circle 没有明确定义 operator Point:

这与static_cast<Point>(c)相同。它创建一个临时 Point 对象,该对象由 Point 的复制构造函数初始化,并以 c 作为参数。这是有效的,因为基础 class 复制构造函数,无论好坏,都可以绑定到派生对象。

明确地说,它不是对 CirclePoint 部分的任何形式的引用。它正在复制 CirclePoint 部分。这称为切片。它丢失了所有 "Circle" 部分信息。

我建议不要这样做。如果没有转换,代码会更好。我想也许 PointCircle 都定义了 operator<< 重载,他想明确地 select Point 一个;在这种情况下,您应该使用 static_cast<Point&>(c) 或等效的 (Point&)c 来查看圆而不是对其进行切片。

注意。首先从 Point 派生 Circle 也是可疑的;继承应表示 "is-a" 关系(而不是 "has-a");但是圆不是点。

进一步阅读:What is object slicing?