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

时间:2011-09-13 23:06:16

标签: c++ reinterpret-cast

这是我的测试示例:

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,那么它可以工作。

3 个答案:

答案 0 :(得分:11)

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

reinterpret_cast获取原始指针并将其视为派生类型。但是,由于virtual继承,必须对指针进行微调,以指向正确的方法调度表,这正是dynamic_cast将要执行的操作。

答案 1 :(得分:1)

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

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

简而言之,reinterpret_cast除了将指针转换为int和back(如果int中有足够的大小来包含指针)之外,还做不了多少。

答案 2 :(得分:0)

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

这里真正的问题应该是:我在设计时知道如何从derived指针计算base指针。如何避免运行时惩罚(dynamic_cast)?

坦率地说,我在这里看不到一个非常好的选项,但可能的选项是将指针存储在根类内的常量指针中的派生类型中,如下所示: / p>

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

这是丑陋和危险的,因为它牺牲了类型安全性能(如果你真的很幸运,你可以获得轻微的运行时性能)。但是,您可以reinterpret_castbase指针(类型为self的{​​{1}}成员)void*指针放入derived