Inside the destructor the this
pointer is well defined, as are all the members and bases (that will be destroyed in construction reverse order after the destructor return). So printing the address it refers is not UB.
The only thing is that the object itself cannot be assumed anymore as "polymorphic", since the derived components had already been destroyed.
class A
{
public:
virtual void fn() { std::cout << "A::fn" << std::endl; }
virtual ~A() { fn(); } //< will call A::fn(), even if B is destroying
};
class B: public A
{
public:
virtual void fn() { std::cout << "B::fn" << std::endl; }
virtual ~B() {}
};
int main()
{
B b;
A& a = b;
a.fn(); //< will print B::fn(), being A::fn virtual and being B the runtime-type of the a's referred object
return 0; //< will print A::fn() from b's A's component destructor
}