繁体   English   中英

来自“void *”的 dynamic_cast

[英]dynamic_cast from “void *”

根据void*没有RTTI信息,因此从铸造void*是不合法的,它是有意义的。

如果我没记错的话,来自void* dynamic_cast正在处理 gcc。

你能澄清一下这个问题吗?

dynamic_cast仅适用于多态类型,即包含虚函数的类。

在 gcc 中,您可以将dynamic_castvoid*但不能

struct S
{
    virtual ~S() {}
};

int main()
{
    S* p = new S();
    void* v = dynamic_cast<void*>(p);
    S* p1 = dynamic_cast<S*>(v); // gives an error
}

5.2.7 - Dynamic cast [expr.dynamic.cast]它说对于dynamic_cast<T>(v)

  • 如果T是指针类型,则v应是指向完整类类型的指针的右值
  • 如果T是引用类型,则v应该是完整类类型的左值(感谢 usta 评论我的遗漏)

...

  • 否则, v应该是指向多态类型的指针或左值

因此,不,不允许使用(void*)

让我们考虑一下您的请求可能意味着什么:假设您有一个真正指向Derived1*的指针,但代码dynamic_cast -ing 只知道它是一个void* 假设您正在尝试将其Derived2*转换为Derived2* ,其中两个派生类都有一个共同的基础。 从表面上看,您可能认为所有的指针都指向同一个Base对象,该对象将包含一个指向相关虚拟调度表和 RTTI 的指针,因此一切都可以挂在一起。 但是,考虑到派生类可能有多个基类,因此所需的Base类子对象可能不是Derived* (仅作为void*可用)所指向的对象。 这行不通。 结论:编译器需要知道这些类型,以便它可以根据所涉及的类型对指针进行一些调整。

Derived1* -----> [AnotherBase]
                 [[VDT]Base]    <-- but, need a pointer to start of
                 [extra members]    this sub-object for dynamic_cast

(有些答案谈到需要将您从其强制转换为具有虚函数的多态类型的指针。这都是有效的,但有点误导。正如您在上面看到的,即使void*是这样的如果没有完整的类型信息,它仍然无法可靠地工作,因为真正的问题是void*可能指向派生对象的开始,而您需要一个指向基类子对象的指针,从中进行转换 -键入派生。)

确实, void*不能被dynamically_cast ed。

你可能记错了。 使用 g++ 4.5 和以下代码

struct A {
    virtual ~A();
};

int main() {
    A a;
    void *p = &a;
    A* pa = dynamic_cast<A*>(p);
}

我收到以下错误:

不能 dynamic_cast 'p'(类型为 'void*')到类型 'struct A*' (源不是指向类的指针)

我猜您将dynamic_castvoid*混淆了。 这是合法的,并获得指向最派生类对象的指针。

来自void* dynamic_cast是非法的 - 所转换的类型必须是多态的 - 至少包含一个虚拟函数(虚拟析构函数也很重要)。

为了补充托尼的好答案,这个小代码片段出于某种原因对我有帮助。 首先,我们建立一个简单的层次结构。 然后,我们看看dynamic_cast可以“生存” static_cast 在这个实验之前,我认为“运行时类型信息在那里,动态转换应该弄清楚”。 现在我意识到“ dynamic_cast必须根据编译器知道的一些表来查找它的信息,所以它不能有什么神奇的力量。”

#include <iostream>
#include <cassert>

using namespace std;

class A {
  protected:
  virtual void foo() { cout << "A" << endl; }
};

class B1 : public A {
  private:
  virtual void foo() override { cout << "B1" << endl; }
};

class B2 : public A {
  public:
  virtual void foo() override { cout << "B2" << endl; }
};

int main(int argc, char **argv) {
  B1 b1;
  // undefined behavior even though dynamic_cast didn't return null
  dynamic_cast<B2*>(
      static_cast<B2*>(
        static_cast<A*>(&b1)))->foo();
  // dynamic_cast returns null here though
  assert (!dynamic_cast<B2*>
          (static_cast<A*>
           (static_cast<B2*>
            (static_cast<A*>(&b1)))));
}

您可以将指向多态类型的指针转​​换为void * ,但反之则不然。

暂无
暂无

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

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