Ваша программа имеет неопределенное поведение, что означает "все может случиться".
Вы запускаете новый поток, который содержит указатель (this) на объект.Этот поток позже вызовет виртуальный метод, что означает, что ему нужно использовать данные из объекта, на который он указывает.Указатель vtable сам по себе является своего рода данными класса.Поскольку вы удаляете свой объект из другого потока, указатель (this) просто указывает на разрушенный объект, и доступ к данным (vtable) из удаленного объекта является неопределенным поведением.
Ваше наблюдение зависит от реализации компилятораи, возможно, также на уровне оптимизации.Возможно, во время деконструкции ваш компилятор перематывает указатель vtable вниз на указатель базового класса.А так как память объекта не переопределена никаким другим контентом (который даже не определен!), Вы можете наблюдать вызов базовой функции после уничтожения.Но это не то, на что вы можете положиться, поскольку вообще не разрешается использовать какой-либо объект после уничтожения, ЕСЛИ вы используете члены-данные объекта, который здесь является указателем vtable.
Вкратце: ваш код содержитошибка, и все может произойти, поскольку это неопределенное поведение.