Enviado em 04/09/2023 - 01:06h 
		Por que você precisa de um 
void * ?
Em C++ (e em Java, C#, D, outras tantas linguagens de OO, e até em C, se você resolver usar GObject ou outra técnica de emulação de OO), o que se costuma fazer quando você tem uma coleção de objetos que não serão necessariamente todos do mesmo tipo é usar uma classe base abstrata, que define a interface (funções-membros virtuais/métodos) comum a todos esses objetos, e derivar a partir dessa classe em todos os objetos que possam vir a fazer parte de tal coleção, que teria de ser uma coleção de ponteiros para/referências a objetos da classe base.
O exemplo clássico seria um vetor de 
forma s, uma classe abstrata que vai ter várias classes concretas delas derivadas.
#include <iostream> 
O que possivelmente não é recomendável — e talvez tenha sido isso o que lhe desencorajaram de fazer — seria ter uma coleção de ponteiros para qualquer coisa (
void * ), e converter essa coisa desconhecida para alguma classe potencialmente diferente do tipo que deveria ter. O compilador não vai reclamar, mesmo com todos os níveis de diagnóstico e alertas ligados, se você fizer, por exemplo, o seguinte, embora seja claramente um código inválido.
/*** CRIANÇAS, NÃO TENTEM ISTO EM CASA!!! ***/ 
Em particular, o que você falou de converter de 
void *  para o tipo que você quer usando 
dynamic_cast  não funciona diretamente — para fazer isso, você teria primeiro de converter de 
void *  para um ponteiro para a classe base usando 
static_cast , e depois converter desse ponteiro-base para um ponteiro da classe derivada usando 
dynamic_cast , certificando-se que o resultado da conversão não é nulo (sem contar eventuais passos adicionais com 
const_cast , se um ou mais dos ponteiros no meio do caminho apontarem para dados constantes). Parece-me natural que essa dupla (ou tripla, ou quádrupla) conversão poderia ser evitada se, em vez de uma coleção de dados de tipos indeterminados e disjuntos, você conseguisse modelar tal coleção para usar essa tal classe base comum, tratando os tipos derivados por meio das funções-membros virtuais sempre que possível, e com 
dynamic_cast  apenas quando estritamente necessário, como o exemplo das formas, acima, mostra.
Se, de todo, for impossível usar uma classe base comum, considere, antes de recorrer a 
void * , a possibilidade de usar 
std::variant  ou 
std::any  como tipo dos elementos da sua coleção.
... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)