Более 1 адрес для объекта производного класса?
В пункте 27 "Эффективный С++" (3-е издание, стр. 118) Скотт Мейерс сказал:
class Base { ... };
class Derived: public Base { ... };
Derived d;
Base *pb = &d;
Здесь мы просто создаем указатель базового класса на объект производного класса, но иногда два указателя не будут одинаковыми. Когда этот случай, смещение применяется во время выполнения к указателю Derived*
, чтобы получить правильное значение указателя Base*
.
Этот последний пример демонстрирует, что один объект (например, объект типа Derived
) может иметь более одного адреса (например, его адрес при указании указателем Base*
и его адресом при указании Derived*
).
Вот немного сложно понять. Я знаю, что указатель на базовый класс может указывать на объект производного класса во время выполнения, это называется полиморфизмом или динамической привязкой. Но действительно ли у объекта производного класса в памяти больше 1 адреса?
Угадайте, у меня есть недоразумение. Может кто-нибудь дать некоторые разъяснения? Может быть, это имеет какое-то отношение к тому, как полиморфизм реализуется в компиляторе С++?
Ответы
Ответ 1
Просто попробуйте:
class B1
{
int i;
};
class B2
{
int i;
};
class D : public B1, public B2
{
int i;
};
int
main()
{
D aD;
std::cout << &aD << std::endl;
std::cout << static_cast<B1*>( &aD ) << std::endl;
std::cout << static_cast<B2*>( &aD ) << std::endl;
return 0;
}
Невозможно, чтобы под-объект B1
имел одинаковый
адрес как под-объект B2
.
Ответ 2
Объект имеет ровно один адрес; что он находится в памяти. Когда вы создаете указатель на подобъект base, вы получаете адрес этого подобъекта, и это не должно быть таким же, как адрес объекта, который его содержит. Простой пример:
struct S {
int i;
int j;
};
S s;
Адрес s
будет отличаться от адреса s.j
.
Аналогично, адрес базового подобъекта не должен быть таким же, как адрес производного объекта. С единственным наследованием, как правило, является, но когда множественное наследование входит в игру и игнорирует пустые базовые классы, не более одного из базовых подобъектов может иметь тот же адрес, что и производный объект. Поэтому, когда вы конвертируете указатель на производный объект в указатель на одну из его баз, вы не обязательно получаете то же значение, что и адрес производного объекта.