Undefined behaviour is undefined.
The moment you dereference (B*)e
, your program has Undefined Behaviour (because e
doesn't actually point to a B
object), so anything can happen. The program could appear to work, it could crash, it could order pizza online.
One possible explanation for the behaviour could be that the layout of D
happens to be such that the C
subobject is first in memory and has the same size as int
(it probably contains just a pointer to the virtual base A
), and that is followed by the A
subobject whose member m_i1
thus has the same offset from a D
object start as the member m_i2
would have of a B
object start. Therefore the code interprets that A::m_i1
as B::m_i2
when executing B::printEFGH()
. But this is pure speculation. As with any UB, literally anything can happen.