如何使用reinterpret_cast转换为c++中的派生类指针

发布于 2024-12-04 10:55:25 字数 532 浏览 0 评论 0原文

这是我的测试示例:

struct base {
    virtual ~base(){}
    int x;
};

struct derived: public virtual base {
    base * clone() {
        return new derived;
    }
    derived(): s("a") {}
    std::string s;
};

int main () {
    derived d;
    base * b = d.clone();
    derived * t = reinterpret_cast<derived*>(b);
    std::cout << t->s << std::endl;
    return 0;
}

它在我打印 s 的行处崩溃。由于“b”是指向派生类的指针,因此reinterpret_cast应该可以工作。我想知道为什么会崩溃。同时,如果我用dynamic_cast替换reinterpret_cast,那么它就可以工作。

Here is my test example:

struct base {
    virtual ~base(){}
    int x;
};

struct derived: public virtual base {
    base * clone() {
        return new derived;
    }
    derived(): s("a") {}
    std::string s;
};

int main () {
    derived d;
    base * b = d.clone();
    derived * t = reinterpret_cast<derived*>(b);
    std::cout << t->s << std::endl;
    return 0;
}

It crashes at the line where I print s. Since "b" is a pointer to the derived class, reinterpret_cast should just work. I wonder why it crashes. At the same time, if I replace reinterpret_cast with dynamic_cast, then it works.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼前雾蒙蒙 2024-12-11 10:55:26

不要reinterpret_cast它,它会导致多重或虚拟继承的问题,就像你的情况一样。简单的 static_cast 不能完成这里的工作吗?

要了解原因,请搜索虚拟继承的实现。常见的一种方法是在对象内存储指向基类的指针,因此虚拟基不会与其派生类共享相同的地址。使用多重继承时也有类似的情况。

简而言之,reinterpret_cast 只能将指针强制转换为 int 并返回(如果 int 中有足够的大小来包含指针)。

Don't reinterpret_cast it, it will cause trouble with multiple or virtual inheritance, like in your case. Wont a simply static_cast do the job here?

To know why, search for implementations of virtual inheritance. A common one is to store a pointer to the base class within the object, so the virtual base does not share the same address than its derived classes. There is a similar case when multiple inheritance is used.

In short, reinterpret_cast can't do much more than casting pointers to ints and back (if there is enough size in the int to contain a pointer).

野味少女 2024-12-11 10:55:26

正如这里的其他答案所建议的,您不能以这种方式使用reinterpret_cast,因为指向base指针的值实际上与不同指向派生的指针的值。有效的指针是在运行时推导出来的,这就是为什么你必须使用dynamic_caststatic_cast 无法工作,因为您在设计时不知道最派生的类(您想要转换为的类)是通过哪种中间类型从您拥有的类型派生的一个指向.

这里真正的问题应该是:我在设计时知道如何从基指针计算派生指针。如何避免(dynamic_cast)的运行时损失?

坦率地说,我在这里没有看到一个真正好的选择,但是一个可能的选项是将指向最派生类型的指针存储在根类内的常量指针中,如下所示

struct base {
  void* const self;
  virtual ~base() {}
  protected:
    base(void* self) : self(self) {}
};
struct derived : public virtual base {
  derived() : base(this) {}
}

:危险的,因为它牺牲了类型安全来换取性能(如果你真的很幸运,你会得到轻微的运行时性能)。但是您将能够将您的 base 指针(void* 类型的 self 成员)reinterpret_cast 转换为 代码>派生指针。

As the other answers here suggested, you cannot use reinterpret_cast in this fashion because the value of the pointer to base actually differs from the value of the pointer to derived. The valid pointer is deduced at runtime which is why you have to use dynamic_cast. static_cast cannot work, as you don't know at designtime through which intermediate type the most derived class (the one you want to cast to) was derived from the type you have a pointer to.

The real question here should be: I know at design time, how to compute the derived pointer from the base pointer. How can the runtime penalty (of dynamic_cast) be avoided?

Frankly, I don't see a really good option here, but a possible option is to store the pointer to the most derived type in a constant pointer inside the root class, like so:

struct base {
  void* const self;
  virtual ~base() {}
  protected:
    base(void* self) : self(self) {}
};
struct derived : public virtual base {
  derived() : base(this) {}
}

This is ugly and dangerous, because it sacrifices type safety for performance (if you are really lucky, you get a slight runtime performance out of it). But you will be able to reinterpret_cast your base pointer (the self member of type void*) into a derived pointer.

总攻大人 2024-12-11 10:55:25

即使b在这里动态派生类型,您也必须使用dynamic_cast。这就是dynamic_cast的用途,在运行时动态地将基类的指针转换为派生类。

reinterpret_cast 接受原始指针并将其视为派生类型。但是,由于虚拟继承,必须对指针进行轻微调整以指向正确的方法调度表,而这正是dynamic_cast将要做的事情。

Even if b is here dynamically of type derived, you have to use dynamic_cast. This is what dynamic_cast is for, to dynamically convert a pointer of a base class into a derived class at runtime.

reinterpret_cast takes the raw pointer and considers it as being of the derived type. However, because of the virtual inheritance, a slight adjustment must be done to the pointer to point to the correct method dispatch table, and that's precisely what dynamic_cast will do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文