【问题标题】:C++ does reinterpret_cast always return the result?C++ reinterpret_cast 总是返回结果吗?
【发布时间】:2017-12-16 01:52:55
【问题描述】:

我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型的类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受指向 B 类型的类的指针。 当函数调用另一个函数时,我提供 reinterpret_cast(a) 作为参数。如果这看起来模棱两可,这里有一个代码示例:

void abc(A * a) {
  if (a->IsA("B")) { //please dont worry much about this line,
                     //my real concern is the reinterpret_cast
    def(reinterpret_cast<B *>(a));
  };
};

既然你知道我如何调用“def”,我想知道 reinterpret_cast 是否真的返回一个 B 类型的指针作为 def 的参数发送出去。 我将不胜感激任何帮助。 谢谢

【问题讨论】:

  • 你会得到一个B*,但这仍然是一件非常糟糕的事情。它很可能不是您期望的指针。相反,你应该做一个static_cast
  • 我会改成static_cast,谢谢。
  • 或者将测试和演员组合成一个dynamic_cast
  • 谢谢,这也是个好主意。

标签: c++ reinterpret-cast


【解决方案1】:

reinterpret_cast 是类型系统损坏的结果。它的行为假设存在一个联合,例如

 union { 
     TypeA anA;
     TypeB aB;
 } a;

所以

 reinterpret_cast< B* >( a );

假设 a 是指向成员 anA 的指针,然后可以传递 aB 地址。

如果类型是同一类层次结构的一部分,那么 static_cast 将允许您在编译时找出是否有足够的信息来执行转换。这通常是当BA 的基类时(单个或多个)。

如果没有足够的信息让 static_cast 起作用,那么可以让 dynamic_cast 起作用。这是B 类型以某种方式从A 派生的情况。

请务必注意,dynamic_cast&lt;B*&gt;( a )static_cast&lt; B*&gt;( a ) 在成功时可能不会产生相同的地址。

那是因为当多重继承时,二级继承会在对象中创建多个类和vtables。发生这种情况时,static_cast、dynamic_cast会调整对象的基地址以找到正确的嵌入类基地址。

dynamic_cast 和 static_cast 可能会改变地址,这就是不鼓励使用 reinterpret_cast 的原因。它可能会导致一个不符合您要求的值。

【讨论】:

    【解决方案2】:

    正如其他人所说,reinterpret_cast 是错误的解决方案,请改用dynamic_cast

    void abc(A * a) {
        B *b = dynamic_cast<B*>(a);
        if (b) {
            def(b);
        }
    }
    

    【讨论】:

      【解决方案3】:

      您将有一个 B* 类型的指针,但 reinterpret_cast 并不是很好。

      如果你确定类型是B,使用static_cast,如果不是,使用dynamic_cast并测试指针(如果dynamic_cast失败,它返回nullptr

      https://stackoverflow.com/a/332086/5303336

      【讨论】:

      • 如果您能详细说明“reinterpret_cast 不是很好”的原因,这个答案将会得到改进。
      • 我添加了一个指向答案的链接,说明为什么它不是很好以及如何正确使用不同的演员表
      【解决方案4】:

      重新解释强制转换总是返回一个指针。它可能不是一个有效的指针,因为它实际上指向 B 类型的对象。

      如果 B 有多个基类,并且 A 不是第一个基类,则重新解释强制转换会做错事,无法对指针进行必要的调整。

      对于您的用例,您应该使用静态转换,其优点是编译器将检查 B 是否实际上是从 A 派生的并执行任何需要的调整。额外的检查不会产生运行时开销,但是如果对象实际上不是 B 类型并且程序将任意失败,则不会发出警告。

      【讨论】:

        【解决方案5】:

        reinterpret_cast 将始终如你所说 - 它是一个大锤。你可以这样做

        def(reinterpret_cast<B *>(42));
        

        std::string hw = "hello";
        def(reinterpret_cast<B *>(hw));
        

        它总是会返回一个可能指向正确类型的指针。它假设您知道自己在做什么

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-02-02
          • 1970-01-01
          • 2016-05-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多