в чем разница между переменной (void *) и переменной (void *&) в С++ при приведении типов

в Как напечатать адрес функции-члена в C++ он использует (void *&) для ввода переменной, я пытался используйте (void *), но с этим что-то не так. я спрашиваю, в чем разница между переменной (void *) и переменной (void *&) в C++ при приведении типов. фрагмент кода по ссылке:

void TestClass::PrintMyFuncAddress(void)
{
  void (TestClass::* ptrtofn)() = &TestClass::MyFunc;
  cout << (void*&)ptrtofn<< endl;
}

person toolchainX    schedule 02.11.2012    source источник
comment
Вы знаете, в чем разница между void * и void *& вообще, и вы просто запутались в приведении?   -  person Useless    schedule 02.11.2012
comment
@Useless void * b; void * &a = b a - это ссылка (или псевдоним) на b, тип которого (void *), я прав?   -  person toolchainX    schedule 02.11.2012


Ответы (2)


Приведение void* пытается преобразовать значение ptrtofun в значение типа указатель на пустоту. С++ не обеспечивает такого преобразования из указателя на функцию-член в void*, поэтому с ним что-то не так (вероятно, он не компилируется).

Приведение void*& создает ссылку, реферандом которой являются первые sizeof(void*) байтов памяти, начиная с первого байта, занятого объектом ptrtofn. ptrtofun не имеет типа void* или совместимого типа и даже не обязательно должен быть того же размера, что и void*. Таким образом, использование ссылки имеет неопределенное поведение (это нарушение строгого алиасинга), но компилятору не нужно обнаруживать проблему.

Практически единственный способ переносимой печати функции указателя на член — это вывести sizeof(ptrtofun) байт, начиная с (unsigned char*)(&ptrtofun). Вы можете решить для себя, как именно вы хотите представлять эти байты (очевидный выбор - шестнадцатеричный), но имейте в виду, что результат не обязательно является адресом в памяти кода для TestClass::MyFunc. Указатели на функцию-член просто так не работают, потому что, например, они должны разрешать указатель на виртуальную функцию, которая будет вызывать другой код в соответствии с динамическим типом вызываемого объекта.

person Steve Jessop    schedule 02.11.2012

Приведение к типу void *& даст вам ссылку на тип void *, что означает, что его можно использовать как l-значение. void * даст r-значение, которое можно использовать в выражении. Но это на самом деле не имеет отношения к вашему вопросу.

Вы не можете преобразовать указатель на функцию-член в указатель на данные или в указатель на функцию; это принципиально разные типы. Обычно sizeof(ptr_to_member_function) != sizeof(void*) (или sizeof(void (*)() в этом отношении).

Указатель на функцию-член не обязательно содержит указатель на начало кода этой функции. Он может содержать смещение к VTBL для виртуальных функций.

Хотя я не уверен, я вполне уверен, что стандарт С++ не допускает этих преобразований.

person Tomek    schedule 02.11.2012