When is static cast safe when you are using multiple inheritance?
You can safely upcast if you are sure that the object is actually an instance of that class.
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
int main()
{
Base* b = new Derived1;
Derived1* d1 = static_cast<Derived1*>(b); // OK
Derived2* d2 = static_cast<Derived2*>(b); // Run-time error - d isn't an instance of Derived2
}
If Derived
has Base
as a public (or otherwise accessible) base class, and d
is of type Derived*
, then static_cast<Base*>(d)
is an upcast.
This is always technically safe.
And generally unnecessary, except for cases where you have hiding (shadowing) of method.
Cheers & hth.,
A cross-cast:
struct Base1 { virtual void f1(); };
struct Base2 { virtual void f2(); };
struct Derived : Base1, Base2 {};
Base1* b1 = new Derived();
Base2* b2 = dynamic_cast<Base2*>(b1);
requires use of dynamic_cast
, it cannot be done with static_cast
(static_cast
should have caused a compile-time error). dynamic_cast
will also fail if either base class is not polymorphic (the presence of virtual functions is NOT optional).
See this explanation on MSDN
The problem lies with this line:
B* a = (B*)cptr;
If you convert something to a void pointer, you must convert it back to the same type that it was converted from first before doing any other casts. If you have a situation where multiple different types of objects have to go through the same void pointer, then you need to first cast it down to a common type before converting to a void pointer.
int main(){
B *bptr = new DD; // convert to common base first (won't compile in this case)
void* cptr = bptr; // now pass it around as a void pointer
B* a = (B*)cptr; // now back to the type it was converted from
D2* b = static_cast<D2*>(a); // this should be ok now
D2* c = dynamic_cast<D2*>(a); // as well as this
std::cout << a << " " <<b << " " <<c;
}
EDIT: If you only know that cptr points to some object which is of a type derived from B at the time of the cast, then that isn't enough information to go on. The compiler lets you know that when you try to convert the DD pointer to a B pointer.
What you would have to do is something like this:
int main(){
void* cptr = new DD; // convert to void *
DD* a = (DD*)cptr; // now back to the type it was converted from
D2* b = static_cast<D2*>(a); // this should be ok now, but the cast is unnecessary
D2* c = dynamic_cast<D2*>(a); // as well as this
std::cout << a << " " <<b << " " <<c;
}
but I'm not sure if that is acceptable in your actual usage.