Почему указатель "this" имеет одинаковое значение внутри производного и первого базового класса - PullRequest
0 голосов
/ 06 февраля 2020

Рассмотрим эти классы, которые будут действовать как базовые классы:

struct Base1 {
   int b1;
   void print_Base1_addr() const { std::cout << this << '\n'; }
};

struct Base2 {
   int b2;
   void print_Base2_addr() const { std::cout << this << '\n'; }
};

Если Derived наследует от Base1 и Base2:

struct Derived: Base1, Base2 {
   int i;
   void print_addr() const { std::cout << this << '\n'; }
};

Тогда этот код печатает тот же адрес для this в Derived и Base1, но не в Base2:

Derived d{}; 

d.print_addr();
d.print_Base1_addr();
d.print_Base2_addr();

Я не понимаю, почему this в Derived имеет такой же адрес, как в Base1. Это не пустые классы, так как все они содержат элемент данных (адреса элементов данных b1 и i отличаются). Как будто Base1 перекрывается с Derived.

Что я пропускаю?

Ответы [ 2 ]

3 голосов
/ 06 февраля 2020

Я не понимаю, почему этот адрес в Derived имеет тот же адрес, что и в Base1.

Почему бы и нет? Производный объект содержит подобъекты базового класса. Подобъекты могут иметь тот же адрес, что и объект-контейнер.

Схема в памяти, вероятно, выглядит примерно так:

mem addr   | 0123456789ab # relative to the address of Derived object
Base1      | 1111         # 1 denotes address occupied by Derived::Base1
Base2      |     2222     # 2 denotes address occupied by Derived::Base2
i          |         iiii # i denotes address occupied by Derived::i
Derived    | DDDDDDDDDDDD # D denotes address occupied by Derived
-------------------------
all subobj | 11112222iiii

Обратите внимание, как начало 1 и D перекрываются по адресу 0.

Как будто Base1 перекрывается с производным.

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

1 голос
/ 06 февраля 2020

Производные классы просто расширяют любые базовые классы. В конце концов, это все один объект, который начинается с одного и того же адреса.

В вашем примере d является экземпляром этого результирующего класса. У него всегда будет один и тот же начальный адрес.

...