Line 72 starts a mini-block that implements the dynamic down cast operator. This is where things get really interesting.
Well, sort of.
Line 75 gets the start address of the X object. It also casts the pointer to a (char *) so we can perform byte-unit pointer computations.
Line 76 computes the expected start address of the Y object, assuming pX is really pointing to the superX of a enclosing Y object. Because a Y object has an extra pointer to its own vtable right before superX, we simply subtract the number of bytes used by the pointer to the vtable to get to the start address of the “hypothetical” Y object.
After the computation, line 74 performs a reinterpret (C-style) cast to make the compiler happy.
Line 77 performs a run-time check to see if the id of the hypothetical Y object matches the actual id of class Y. If there is no match, the pointer becomes NULL (which is just 0). It is possible that, just by chance, that the 32-bit integer just so happens to have a value that matches, even though pX is not pointing at a superX data member of a Y object.
This is why it is important to use a hash value instead of sequential number for the id of a class. It is just too common to have a 32-bit integer storing a value of 1.