C ++: расположение в памяти классов с использованием наследования

Я знаю, как данные будут упакованы не указано в стандарте. Я просто пытался получить представление о расположении памяти классов (особенно как dynamic_cast<void*> гарантирует возврат указателя на начало самого производного класса). Я не мог придумать никакого объяснения о выводе следующего кода:

struct A{ int a;};
struct B{ int b;};
struct C: public A, public B { int c;};
struct D:public C {int d;};int main(){
D* ob=new D;
A* a = ob;
B* b = ob;
C* c = ob;
}

Печать значений указателей показывает, что a,c,d имеют всегда одно и то же значение, только b добавлено 4 байта в качестве смещения. Это случайно? Или за этим стоит логика?

Редактировать:
Концептуально макет должен быть похож на изображение, но каким-то образом точки A, C и D сливаются в единицу.введите описание изображения здесь

2

Решение

Во-первых, ваш struct A является

| int a |

а также B является

| int b |

struct C наследуется struct A а также struct Bи он также имеет одного члена, int c, Таким образом, он может иметь такой макет:

            struct B
struct A     /
\        /
| int a | int b | int c |

а также struct D, который наследует struct C, является

            struct B
struct A     /
\        /
| int a | int b | int c | int d |
\-----------------------/
struct C

Теперь подумай D* ob = new D;, Это будет так:

| int a | int b | int c | int d |
^
\
ob

И думать о A* a = obstruct A по смещению 0 из struct D, Так что, это

| int a | int b | int c | int d |
^
\
a

Это равно struct c,

Однако когда дело доходит до struct Bэто смещение 4 (если sizeof(int) == 4), Так что это —

| int a | int b | int c | int d |
^
/
b


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

Для более подробной информации, я предлагаю вам прочитать C ++ Многократное наследование памяти с "Пустые классы".

6

Другие решения

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

0

Печать значений указателей показывает, что a, c, d всегда имеют одинаковое значение, только b добавляется 4 байта в качестве смещения.

В объекте D субобъект C стоит на первом месте, поэтому не удивительно, что он имеет тот же адрес, что и полный объект D (что вы ожидаете до объекта C? начало D?)

В объекте C подобъект A идет первым, поэтому не удивительно, что он имеет тот же адрес, что и объект C, и поэтому, если C является подобъектом D, он также имеет тот же адрес как полный объект D.

Это случайно? Или за этим стоит логика?

Это не случайно. Это определяется ABI вашего компилятора. Ряд компиляторов следуют Itanium C ++ ABI какие документы, как классы должны быть расположены.

0
По вопросам рекламы [email protected]