7

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.

3 Answers 3

15

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Weren't for the virtual inheritance, static_cast would have worked. There is no need to go runtime when you know for sure your base is a derived.
Yes, you are right, if I remove virtual and make it just struct derived: public base, then reinterpret_cast works too (at least, there are no crashes)
K-ballo: you know, the ugly rules of inheritance when building libraries (you don't know if in the future a class will be inherited via two paths) force you to sometimes abuse virtual inheritance just in case.
1

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

3 Comments

In this case compiler says that error: cannot convert from base 'base' to derived type 'derived' via virtual base 'base'
You cannot statically cast from a virtual base. So you have to dynamic_cast here (which implies runtime penalties). Besides that, I agree that reinterpret_cast is evil!
Then you should go with dynamic_cast instead.
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.