Подтвердить что ты не робот

Адрес печати виртуальной функции-члена

Я пытаюсь напечатать адрес виртуальной функции-члена. Если я знаю, какой класс реализует функцию, которую я могу написать:

print("address: %p", &A::func);

Но я хочу сделать что-то вроде этого:

A *b = new B();

printf("address: %p", &b->func); 
printf("address: %p", &b->A::func);

Однако это не компилируется. Возможно ли сделать что-то подобное, возможно, глядя на адрес в таблице vtable во время выполнения?

4b9b3361

Ответ 1

В настоящее время нет стандартного способа сделать это в С++, хотя информация должна быть доступна где-то. В противном случае, как программа могла вызвать функцию? Однако GCC предоставляет расширение, которое позволяет нам получить адрес виртуальной функции:

void (A::*mfp)() = &A::func;
printf("address: %p", (void*)(b->*mfp));

... при условии, что функция-член имеет прототип void func(). Это может быть очень полезно, если вы хотите кэшировать адрес виртуальной функции или использовать ее в сгенерированном коде. GCC предупредит вас об этой конструкции, если вы не укажете -Wno-pmf-conversions. Это маловероятно, что он работает с любым другим компилятором.

Ответ 2

Указатели на функции-члены не всегда являются простыми адресами памяти. См. Таблицу в в этой статье, в которой указаны размеры указателей на функции для разных компиляторов - некоторые идут до 20 байтов.

В статье описывается, что указатель на функцию-член представляет собой блок данных, определенных для реализации, чтобы помочь разрешить вызов через указатель. Вы можете хранить и называть их ОК, но если вы хотите их распечатать, что вы печатаете? Лучше всего рассматривать его как последовательность байтов и получать его длину через sizeof.

Ответ 3

Не имеет для меня большого смысла. Если у вас нормальная функция:

void f( int n ) {
}

то вы можете взять его адрес:

f

но вы не можете взять адрес функции вызов, что вам, похоже, нужно делать.

Ответ 4

Из того, что я могу сказать в стандарте, единственный раз, когда вы получаете динамическое связывание, - это вызов виртуальной функции. И как только вы вызвали функцию, вы выполняете инструкции внутри функции (т.е. Вы не можете "остановить на полпути" в вызове и получить адрес.)

Я думаю, что это невозможно.