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

how to use reinterpret_cast to cast to a derived class pointer in c++

本文关键字:转换 cast 派生 指针 reinterpret c++      更新时间:2023-10-16

下面是我的测试示例:

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应该正常工作。我想知道为什么它会崩溃。同时,如果我将reinterpret_cast替换为dynamic_cast,那么它就可以工作了。

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

reinterpret_cast接受原始指针,并认为它是派生类型。然而,由于virtual的继承,必须对指针做一些调整,以指向正确的方法调度表,这正是dynamic_cast将要做的。

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

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

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

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

这里真正的问题应该是:我知道在设计时,如何从base指针计算derived指针。如何避免(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转换为derived指针。