When you cast a D* to A*, via static_cast or dynamic_cast, the compiler will inject the necessary arithmetic for you.

But when you cast it via reinterpret_cast, or cast a D** to A**, which is the same thing, the pointer will keep its numeric value, because the cast does not give the compiler the right to dereference the first layer to adjust the second layer.

But then the pointer will still point at D's vtable, not A's vtable, and therefore won't be recognized as A.