Размер полиморфного класса выведен практически

Я испытываю трудности с пониманием, и что составляет размер следующих классов?
Я использую MSVS 2008 (компилятор VC 9.0).
Я читал, что если я не объявлю виртуальные функции (в приведенном ниже примере), тогда класс D будет содержать 2 дополнительных указателя (1 из B и другой из C), который будет указывать на общий экземпляр A.

Но какова будет карта памяти каждого класса в следующем случае (также с виртуальными функциями)?

class A
{
public:
int a;
virtual void Func();
public:
A(void);
~A(void);
};

class B :virtual public A
{
public:
int b;
virtual void Func();
public:
B(void);
~B(void);
};

class C: virtual public A
{
public:
int c;
virtual void Func();
public:
C(void);
~C(void);
};

class D : public B, public C
{
public:
int d;
virtual void Func();
public:
D(void);
~D(void);
};int _tmain(int argc, _TCHAR* argv[])
{
cout << "size of Class A :" << sizeof(A) << endl;

cout << "size of Class B :" << sizeof(B) << endl;

cout << "size of Class C :" << sizeof(C) << endl;

cout << "size of Class D :" << sizeof(D) << endl;

return 0;
}

Выход:
размер класса А: 8
размер класса B: 20
размер класса C: 20
размер класса D: 32

Здесь, как размер B, C & Будем рассчитываться?

РЕДАКТИРОВАТЬ: Ниже приведена карта памяти, созданная параметром компилятора / d1reportSingleClassLayoutXXX для каждого класса:

1>class A size(8):
1> +---
1> 0 | {vfptr}
1> 4 | a

1>class B size(20):  //Similar for C
1> +---
1> 0 | {vbptr}
1> 4 | b
1> +---
1>8 | (vtordisp for vbase A)
1> +--- (virtual base A)
1>12 | {vfptr}
1>16 | a
1> +---

1>class D size(32):
1> +---
1> | +--- (base class B)
1> 0 | | {vbptr}
1> 4 | | b
1> | +---
1> | +--- (base class C)
1> 8 | | {vbptr}
1>12 | | c
1> | +---
1>16 | d
1> +---
1>20 | (vtordisp for vbase A)
1> +--- (virtual base A)
1>24 | {vfptr}
1>28 | a

Что означает vtordisp для vbase X?

8

Решение

Я бы сказал, что вы находитесь на 32-битной машине, где sizeof(int) это 4.

Спекулятивно:

Во-первых, размер А:

|int a (4)|vtable pointer A (4)|

Во-вторых, размер B и C:

|A base instance (8)|pointer to A(4)|int b/c(4)|vtable pointer B/C|

В-третьих, размер D:

|A base instance (8)|pointer to A(4)|int c(4)|vtable pointer B(4)|pointer to A(4)|int d(4)|vtable pointer C(4)|

поскольку D практически не наследуется от C, это может позволить себе использовать повторно vtable pointer C, Опять же, это просто предположение. Вы должны попытаться сбросить память объекта D, чтобы быть уверенным. И я не уверен, как ваша машина выравнивает память.

1

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

Согласно Джонатан Кейвс, MSFT

Он используется очень редко — но мы должны добавить его к классам, которые наследуются от виртуальной базы
Класс и переопределить виртуальные функции на случай, если пользователь вызовет виртуальную функцию в
конструктор или деструктор.

Итак, это решение MSVC (ужасно недокументированное) «как вы делаете виртуальный вызов во время строительства объекта?».

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector