Concordo com a resposta do @ j6t, mas aqui está um raciocínio expandido com referências padrão.
O comportamento especial de dynamic_cast
objetos 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_cast
se 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_cast
refere-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_cast
comportamento se comportará como se *this
fosse um objeto do tipo mais derivado Base2
e, portanto, o elenco a Base1
que nunca será bem-sucedido, porque Base2
nã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.