You can look up what the standard has to say about
dynamic_cast
when multiple inheritance is involved, but I'm going to live dangerously and not bother.
The first (hidden) data member of every object that has a virtual function is a
vptr
. It points to a table of function pointers, one for each virtual function in that class. That table is shared by all objects in the class, with each
vptr
pointing to it. The compiler assigns each virtual function an index into that table so that a virtual function can then invoked by
vptr->table[index](args);
If an object belongs to a class that uses multiple inheritance, it will have more than one
vptr
, and they will appear consecutively as the first members in the object.
When you
dynamic_cast
X*
to an
A*
, it isn't a problem because
A
's
vptr
is the first one in an
X
. However, when you try to
dynamic_cast
X*
to a
B*
or
C*
, the resulting pointer would have to reference a
vptr
that is
not at the top of the object. So if you later did a
delete
on that pointer, it would think the object started at the location of that
vptr
when it actually didn't. Returning the object's memory to the heap would cause an exception or heap corruption, because it doesn't start at the same address as the block that was originally allocated. So the standard probably says that, in the case of multiple inheritance, an object of that class can only be dynamically cast to the
first of its multiple base classes.
EDIT: If the target class (
B
or
C
) didn't have any virtual functions, the
dynamic_cast
would probably work: that class doesn't
have a
vptr
, so the pointer could still reference the top of the original object (
A
's
vptr
).
However, if any of
A
,
B
, or
C
had a
data member, my guess is that the
dynamic_cast
would always fail. Why? Because to access a data member, the compiler takes a pointer to the object and adds an offset. But if there are extra
vptr
s in there because the underlying class uses multiple inheritance, that offset would be wrong.