Reputation: 73
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
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
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
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