If we use multiple inheritance, slicing will make the addresses to parent objects differ from the address to leaf objects:
struct X {int x};
struct Y {int y};
struct Z : X, Y {int z};
So if we have a Z
object z
, its address &z
will not coincide with the address of its Y
parent: static_cast<Y*>(&z)
is four bytes higher than &z
.
The good thing about static_cast
is that it's, well, static, so doesn't take up runtime (compared to dynamic_cast
, that is).
However, if we have a Z*
that points at 0
, every cast to a parent should and does yield a null pointer as well.
Why does this work and how is it implemented? Does that imply that every single static_cast
introduces a branch instruction?
Yes, both an implicit conversion from a pointer to a derived class to a pointer to a base class and a
static_cast
back again must preserve null pointer values. This means that a branch is usually required in the generated code for multiple inheritance cases where the base class address does not coincide with the derived class address.It's theoretically possible for an implementation to reserve a range of addresses around a 'zero' address to represent null pointers and avoid the branch in this case but it would be at the expense of adding extra checking for comparisons of null pointers.