【问题标题】:c++ static_cast and referencesc++ static_cast 和引用
【发布时间】:2013-10-30 13:03:12
【问题描述】:
struct A{};
struct B : A{};

int main()
{
    A a;
    A& a_ref = a;

    static_cast<B>(a); // *1
    static_cast<B&>(a_ref); // *2

    return 0;
}

(*1) 产生错误,我明白为什么。 (*2) 编译得很好,但是为什么呢?而且,只要它编译并假设B 包含一些属性,如果我将a_ref 转换为B&amp; 然后尝试访问这些属性会怎样?我想我会有一个运行时错误或其他东西。

所以,正如我所见,有一种情况会导致崩溃,并且没有办法避免它,这与 dynamic_cast 不同,在 try-catch 中,人们可以检查转换为 null 的结果或将代码放入 try-catch地区。我该如何处理这种需要投射参考并确保我真的得到正确参考的情况。

【问题讨论】:

  • 你必须知道你在用static_cast做什么,错误使用的静态转换结果没有运行时异常。
  • 您可以使用static_cast 将左值向下转换为派生类的引用,因为这种方式没有隐式转换(与从派生类转换为基类相反)。 如果你事先知道它是安全的(即你要转换的左值是派生类型或派生的),你应该只将它用于那个目的。
  • 可能XY Problem。为什么需要对派生类型的引用?
  • @JohnDibling:我需要它来将 A& 转换为 B& 并使用属性。
  • 编译器只会发现某些类型的问题。单独使用*2 行似乎很好,因为在某些情况下将A&amp; 转换为B&amp; 是有效的。编译器必须进行更复杂的分析才能确定在这种情况下它实际上是无效的。这可能太难或太慢而无法实现。

标签: c++ static-cast


【解决方案1】:

来自标准 n3337 草案 5.2.9/2

“cv1 B”类型的左值,其中 B 是类类型,可以转换为类型“对 cv2 D 的引用”,其中 D 是类 从 B 派生(第 10 条),如果存在从“指向 D 的指针”到“指向 B 的指针”的有效标准转换(4.10), cv2 与 cv1 具有相同的 cv 限定或大于 cv1 的 cv 限定,并且 B 既不是虚拟基类 D 的基类也不是 D 的虚拟基类的基类。

在你的情况下:

BA派生的类,都是非常量,A*B*的转换是允许的,A不是D的虚拟基类。

【讨论】:

    【解决方案2】:

    static_cast&lt;&gt; 只会检查类型是否兼容

    如果没有运算符来描述 A 和 B 之间的 copy 关系,因此类型 1 不直接兼容

    在情况 2 中,转换是引用转换,就编译器而言,A* 可以转换为 B*,因为它们是兼容的。编译器将不知道指针a_ref 持有什么,这就是它允许您使用它的原因。 dynamic_cast&lt;&gt; 也会检查指针指向的类。

    【讨论】:

      【解决方案3】:

      这就是我使用boost::polymorphic_downcast (doc) 的原因之一——在调试中它使用dynamic_cast 后跟断言,而在发布中它是static_cast,因此不会影响性能。

      【讨论】:

      • 感谢您的信息,我会检查boost::polymorphic_downcast
      【解决方案4】:

      (*2) 编译得很好,但是为什么呢?

      一般来说,你不能静态检查动态类型;而static_cast 不做任何动态类型检查。它允许根据静态类型可能有效的任何转换,包括根据动态类型无效的转换。

      如果我将 a_ref 转换为 B& 然后尝试访问属性会怎样?

      未定义的行为。如果您使用static_cast,那么您有责任确保转换有效。

      我必须如何处理这种需要转换引用并确保我真的得到正确的引用的情况。

      对于多态类型,使用dynamic_cast。应用于引用,如果转换无效,它将抛出std::bad_cast

      对于非多态类型,你自己做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-30
        • 2011-01-16
        • 2018-04-30
        • 1970-01-01
        • 2020-03-21
        • 1970-01-01
        • 1970-01-01
        • 2021-08-06
        相关资源
        最近更新 更多