Concordo com a resposta do @ j6t, mas aqui está um raciocínio expandido com referências padrão.
O comportamento especial de dynamic_castobjetos em construção e destruição é descrito por [class.cdtor] / 5 do padrão C ++ 17 (rascunho final) e equivalentemente pelas versões padrão anteriores.
Em particular, diz:
Quando a dynamic_casté usado em um destruidor, [...] se o operando de dynamic_castse refere ao objeto em construção ou destruição, esse objeto é considerado o objeto mais derivado que possui o tipo de [ classe do destruidor. Se o operando do dynamic_castrefere-se ao objeto em [...] destruição e o tipo estático do operando não é um ponteiro ou objeto da [...] própria classe do destruidor ou de uma de suas bases, o dynamic_cast resulta em comportamento indefinido.
O comportamento indefinido não se aplica aqui, pois o operando é a expressão this, que trivialmente tem o tipo de um ponteiro para a própria classe do destruidor, uma vez que aparece no próprio destruidor.
No entanto, a primeira frase afirma que o dynamic_castcomportamento se comportará como se *thisfosse um objeto do tipo mais derivado Base2e, portanto, o elenco a Base1que nunca será bem-sucedido, porque Base2não é derivado de Base1, e dynamic_cast<Base1*>(this)sempre retornará um ponteiro nulo, resultando no comportamento que você está vendo.
cppreference.com afirma que o comportamento indefinido ocorre se o tipo de destino da conversão não for o tipo da classe do destruidor ou uma de suas bases, em vez de aplicar isso ao tipo de operandos. Eu acho que isso é apenas um erro. Provavelmente, a menção de " novo tipo " no ponto 6 da bala deveria dizer " expressão ", o que faria corresponder à minha interpretação acima.