Typ void to typ niekompletny. Brak w nim informacji w jaki sposób go instancjonować w związku z tym obiekty typu void są niedozwolone. Nie można mieć ani obiektu ani referencji do niego ani także kontenerów z void. Typ ten zwracany jest z funkcji jako sygnał że... funkcja nic nie zwraca. Np. w języku Pascal lub podobnych, takie funkcje nazywane są procedurami.
Typ void *, stosowany jest do przechowywania adresu. Pozbawiony jest on informacji o tym na co wskazuje (na jaki typ) więc nie można go wyłuskać. Poddaje się w języku C i C++ rzutowaniu na wskaźnik dowolnego typu oraz ew. alokacji i dealokacji pamięci. Typ void * bywa stosowany na niskim poziomie do operowania na adresach na rejestry, "wskazywania miejsca". Tam gdzie decyzja o interpretacji typu (jego wielkości i znaczeniu), powinna być podjęta nieco później. Wskaźnik na void, może być gromadzony w kontenerach oraz przypisany do odpowiedniej zmiennej. NIe poddaje się jednak prawidłowej arytmetyce wskaźników (np. dodanie/odjęcie) bo nie wiadomo ma jaką wielkość wskazuje i w konsekwencji co ma być wynikiem. Do arytmetyki "co 1", bywa stosowany wskaźnik na char. void * bywa stosowany do sygnalizacji zwolnienia zasobu, wskazanie na nullptr (w C NULL).
W języku jakim jest C (bez plusów), gdzie nie występuje polimorfizm, void * bywa stosowany do tworzenia funkcji uniwersalnych (popatrz na qsort
http://en.cppreference.com/w/c/algorithm/qsort ). Dopiero w innych funkcjach (w ich wnętrzu) następuje nadanie znaczenia wskaźnikowi.
Jednym słowem... w C++ jeśli nie schodzisz nisko do rejestrów sprzętowych, oprócz sygnalizacji "braku typu" w zasadzie (upraszczając) tylko jako typ zwracanej funkcji. Jeśli występuje, coraz częściej świadczy o nieprzemyślanej arch. rozwiązania. Upraszczając bo w kilku innych miejscach (np. przy szablonach) czasem się przydaje :-)