Трюк с данными
Ваш трюк основан на предположениях о расположении памяти вашего объекта. К счастью для вашего конкретного примера, с вашим компилятором это работает.
Если я скомпилирую этот код с помощью MSVC2013, он вообще не будет работать!! В конце концов я мог бы узнать, что это работает, когда я использую массив short
вместо int
, если бы я добавил некоторые подсказки в конструктор:
A(int t) { a = t; cout << "A: " << (void*)this << " a: " << (void*)&a << " rel:" << (char*)&a - (char*)this << endl; }
Вывод: вы не можете полагаться на это вообще (даже на ваш компилятор в более сложных примерах). Стандарт дает очень ограниченную гарантию относительно относительных адресов памяти членов :
Раздел 9.2/15: Нестатические элементы данных класса (не объединенного) с одинаковым контролем доступа выделяются таким образом, чтобы более поздние члены имели более высокие адреса в объекте класса. Порядок размещения нестатических элементов данных с различным контролем доступа не определен. Требования выравнивания реализации могут привести к тому, что два соседних элемента не будут выделены сразу друг за другом; (...)
Кроме того, ваш трюк может создать псевдоним указателя. Таким образом, компилятор делает предположение о ваших указателях и членах вашего объекта, которые могут быть недействительными, что приводит к сбою сгенерированных оптимизаций.
Трюк с функциями
Для адреса вашей функции все еще хуже. Это снова не определено в стандарте и зависит от реализации.
Обычно используемая реализация виртуальных функций основана на конкретных классах vtables. Каждый полиморфный объект имеет где-то в классе указатель на его виртуальную таблицу (обычно в первых нескольких байтах объекта.
Относительное положение указателя функции в виртуальной таблице зависит от всех виртуальных функций класса и всех унаследованных классов. В вашем примере с MSVC2013 мне удалось вызвать функцию:
typedef int (A::*fptr)();
fptr pf = (*(fptr**)x)[0]; // first unction in vtable
(x->*pf)(); // call it.
Но, конечно же, это совершенно нестандартно и крайне опасно!
И имейте в виду, что для не виртуальных функций вы вообще не можете получить адрес от объекта.
person
Christophe
schedule
24.02.2015