void* pn = static_cast<void*>(&n);
- неявное преобразование;Вы также можете написать
void *pn = &n;
Это означает, что pn
хранит указатель на некоторый тип объекта;программист отвечает за знание того, что это за тип объекта.Чтобы выполнить откат, вам нужно static_cast
:
int *pi = static_cast<int*>(pn);
Обратите внимание, что использование static_cast
для приведения к любому типу, значительно отличающемуся от оригинала (float
значительно отличается, const int
- нет)это способ сделать реинтерпретацию.Вы должны записать, что reinterpret_cast
неявное преобразование (или static_cast
), за которым следует static_cast
.
В этом и заключается цель void*
, концепции, прослеживающей до C, где приведение написано сОчевидно, в стиле C (не static_cast
...), но имеют иное идентичное значение.
Возвращаясь к синтаксису объявлений в C и C ++:
Объявление указателя на int
равно int (*pi);
(скобки бесполезны, но помогают проиллюстрировать смысл), вы можете прочитать его следующим образом: Я заявляю, что выражение (*pi)
имеет тип int
.Вы можете прочитать объявление функции следующим образом: в int f(int i);
я заявляю, что если i
имеет тип int
, то f(i)
имеет тип int
.
Объявление void (*pi);
выглядит как указательк void
, но нет такого понятия, как объект типа void
, выражение *pi
даже не очень хорошо сформировано, оно не имеет смысла.Это особый случай в системе типов: синтаксис говорит «указатель на пустоту», семантический - «указатель на что-то».
В C и C ++ объект указателя является первым классомобъект, и вы можете взять его адрес и иметь указатель на указатель и т. д. (В отличие от Java, где ссылки, как и другие фундаментальные типы, не являются объектами класса.)
Таким образом, вы можете иметь int**
, int***
... указатели на (указатели ... на int
);по той же причине вы можете иметь void**
: объявлено как указатель на (указатель на пустоту), семантически указатель на (указатель на что-то).
Так же, как указатель на int
не может бытьприсваивается указатель на float
без приведения:
float *f = &i; // ill-formed
из-за несоответствия типов, тип, отличный от void**
, не может быть присвоен void**
: результатудля разыменования void**
должен быть void*
объект .