In most cases, it is illegal to access an object of one type as though it were a different type (disregarding cv-qualifiers). Example:

float x = 42;
int y = reinterpret_cast<int&>(x);

The result is undefined behavior.

There are some exceptions to this strict aliasing rule:

A related rule is that if a non-static member function is called on an object that does not actually have the same type as the defining class of the function, or a derived class, then undefined behavior occurs. This is true even if the function does not access the object.

struct Base {
};
struct Derived : Base {
    void f() {}
};
struct Unrelated {};
Unrelated u;
Derived& r1 = reinterpret_cast<Derived&>(u); // ok
r1.f();                                      // UB
Base b;
Derived& r2 = reinterpret_cast<Derived&>(b); // ok
r2.f();                                      // UB