Я знаю, что могу получить указатель на член данных для класса или структуры, но последняя строка следующего кода не скомпилируется:
struct abc
{
int a;
int b;
char c;
};
int main()
{
typedef struct abc abc;
char abc::*ptt1 = &abc::c;
void *another_ptr = (void*)ptt1;
}
почему я не могу конвертировать ptt1 в another_ptr? Мы говорим об указателях, поэтому один указатель должен иметь размер, аналогичный другому (хотя концептуально другой)
указатель на нестатический тип члена класса это не то же самое, что тип указателя объекта; они ведут себя совсем по-другому. На самом деле, вы даже не можете разыменовать указатель на член с *
, Чтобы получить доступ к члену через указатель на член, вы используете .*
а также ->*
операторы вместо. если ты мог приведите его к типу указателя объекта следующим образом: что произойдет, если вы разыменовываете его с помощью *
?
Только указатели на объекты имеют стандартное преобразование в void*
(§4.10):
Значение типа «указатель на резюме
T
,» гдеT
является типом объекта, может быть преобразовано в значение типа «указатель на резюмеvoid
».
Они настолько отличаются, что стандарт даже делает все возможное, чтобы убедиться, что термин «указатель» не включает указатели на нестатические элементы (§3.9.2):
За исключением указателей на статические элементы, текст, ссылающийся на «указатели», не относится к указателям на элементы.
Основная причина в том, что нет требования
указатель на член имеет тот же размер и представление, что и
указатель на данные. На практике трудно представить указатель
чтобы член данных не мог вписаться в void*
, поскольку
указатель на элемент данных действительно должен содержать только
смещение. Грубо говоря, указатель на член данных будет
никогда не должен быть больше чем size_t
и void*
должно быть
по крайней мере, такой же большой, как size_t
, С другой стороны, это может
легко содержать битовые шаблоны, которые не были допустимы в указателе.
На самом деле, как отмечает Стив Джессоп, указатели на член требуют дополнительной информации, поскольку, если член находится в виртуальной базе, его смещение зависит от самого производного класса и должно вычисляться динамически на основе дополнительной информации в указателе.
В целом, void*
может содержать только указатель на данные.
Он должен быть таким же большим, как самый большой указатель данных (обычно
char*
), но указатели на функции и указатели на элементы могут
быть больше и не соответствовать (и указатель на функции-члены почти
никогда не подходит).
Вы пытаетесь сделать что-то подобное?
struct ABC
{
int a;
int b;
char c;
};
int main()
{
ABC abc;
char *ptt1 = &abc.c;
void *another_ptr = (void*)ptt1;
}