Получить адрес базового объекта из производного объекта - PullRequest
1 голос
/ 19 июня 2011

Я получаю очень запутанную ошибку в моей программе. Я думаю, что у меня может быть два разных объекта одного и того же класса, где я думал, что у меня один и тот же объект. Это сбивает с толку, потому что я имею дело с очень большой структурой, где не просто получить указатель на нужный мне объект.

У меня вопрос: если у меня есть класс Derived, который наследуется от Base, и у меня есть указатель на объект Derived, как я могу получить адрес объекта Base из производного объекта? Я работаю с исходным кодом базового класса и распечатываю адрес "this" в Base. В другой части моего кода получить указатель на производное. Мне нужно иметь возможность печатать адрес базового объекта через мой производный объект, чтобы определить, есть ли у меня указатель на конкретный производный объект, который мне нужен.

У меня может быть большое недопонимание того, как адреса работают в C ++ при наследовании. Возможно, это всего лишь один объект, а не базовый объект, связанный с производным объектом?

Большое спасибо

Edit: Причина, по которой я хочу сделать это исключительно для отладки. Проблема в том, что используемая кодовая база не содержит много интерфейсов или защищенных элементов, поэтому мне приходится редактировать исходный код для доступа к определенной части информации. Однако моя программа падает, когда я вызываю метод, добавленный в базовый класс, используя определенный указатель производного. Мне нужно иметь возможность напечатать адрес базового объекта в этом случае, чтобы я мог определить, является ли это правильный объект или я получаю эту ошибку, потому что у меня фактически есть указатель на неправильный объект. Я понимаю, что могу добавить код в производный класс, чтобы заставить его печатать свой адрес, но мне было просто интересно, можно ли получить адрес без редактирования исходного кода больше. Спасибо

Ответы [ 3 ]

5 голосов
/ 19 июня 2011

Переход от указателя к производному классу к указателю на базовый класс очень прост:

Derived * derived_ptr = < some pointer >;
Base * base_ptr = derived_ptr;

Если вы хотите быть педантичным, вы можете использовать static_cast в правой части задания:

Base * base_ptr = static_cast<Base*>(derived_ptr);

Переход от указателя к базовому классу к указателю на производный класс использует dynamic_cast:

Derived * derived_ptr = dynamic_cast<Derived*>(base_ptr);

Однако это не всегда будет работать.Вам необходимо включить typeid во время выполнения, а в базовом классе должен быть хотя бы один виртуальный метод.

Прежде чем вы приступите к этому, зачем переходить от базового указателя к производному указателю?Это ключ к разгадке вашего дизайна.

2 голосов
/ 19 июня 2011

Существует только один объект, он состоит из Основы и Производного, то есть Основа помещается в память прямо рядом с Производным, в большинстве реализаций.Это означает, что Base * не совпадает с Derived * в общем случае, но они будут очень близки.

Теперь вы можете тривиально получить Base * из Derived *, приведение неявно,но вы также можете сделать это явным:

Derived* dptr = ...;
Base* ptr = dptr;

Однако ничто не мешает одному производному объекту содержать несколько Base объектов.Обычно это не так, но это может случиться.Это означает, что вы не можете сравнивать Base указатели и ожидать, что вы имеете дело с тем же объектом, только с тем же субобъектом Base.

1 голос
/ 19 июня 2011

В простом случае одиночного наследования с большинством компиляторов:

Если у вас есть указатель на производный класс, то это то же самое, что указатель на базовый класс. Оба указателя имеют одинаковое значение и указывают на один и тот же адрес памяти.

В памяти, если вы создадите экземпляр производного класса, он будет размечен как члены базового объекта, за которым следуют члены производного объекта. Члены базового класса являются частью производного объекта.

class Base
{
   int b;
};

class Derived : public Base
{
   int d;
};

В памяти скажем, что производный указатель равен 0400. Затем:

0400 byte 1 of b
0401 byte 2 of b
0402 byte 3 of b
0403 byte 4 of b
0404 byte 1 of d
0405 byte 2 of d
0406 byte 3 of d
0407 byte 4 of d

Производный объект состоит из базовых членов и собственных производных элементов, а адрес обоих из них начинается с 0400.

Так получилось, что в 0400 часть базового объекта производного находится. Итак, base и производные имеют один и тот же адрес.

...