Andrei
Andrei

Reputation: 73

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

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.

Upvotes: 7

Views: 10576

Answers (3)

bitmask
bitmask

Reputation: 34636

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.

Upvotes: 1

Diego Sevilla
Diego Sevilla

Reputation: 29021

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.

Upvotes: 15

K-ballo
K-ballo

Reputation: 81379

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).

Upvotes: 1

Related Questions