Given this sample:
class Base
{
public:
void foo() {};
};
class Derived : public Base
{
};
int main()
{
Base b;
Derived* d = static_cast<Derived*>(&b);
d->foo();
}
I just have three cases: when void foo()
:
Base
,Derived
,Base
and Derived
.My questions are:
Does the member access expression d->foo()
is undefined behavior in all three cases?.
If the member access expression is UB, Does the only workaround is to use dynamic_cast
?
From the C++ standard §7.6.1.9.11
A prvalue of type “pointer to cv1
B
”, whereB
is a class type, can be converted to a prvalue of type “pointer to cv2D
”, whereD
is a complete class derived fromB
,...
If the prvalue of type “pointer to cv1
B
” points to aB
that is actually a base class subobject of an object of typeD
, the resulting pointer points to the enclosing object of typeD
. Otherwise, the behavior is undefined.
So using static_cast
to downcast is only valid if you know (via some other means) that the cast is valid. If you take a Base
that isn't a Derived
and use a static_cast
to pretend that it is, you've invoked undefined behavior, even before you try to dereference the pointer. So you could remove the d->foo()
line and still have undefined behavior. It's the cast that's bad.
If your goal is to conditionally check whether you've got an instance of a subclass, then you want dynamic_cast
.