размер класса в виртуальном наследовании
Размер классов, как следует при использовании виртуального наследования..
ABase=4(sizeof imem)
BBase=12(sizeof imem+ABase+VBase_ptr)
CBase=12(sizeof imem+ABase+VBase_ptr)
Это оправдано, но я не понимаю, почему размер ABCDerived
равен 24.
class ABase{
int iMem;
};
class BBase : public virtual ABase {
int iMem;
};
class CBase : public virtual ABase {
int iMem;
};
class ABCDerived : public BBase, public CBase {
int iMem;
};
2 ответа:
Это будет крайне зависимо от платформы, но я думаю, что мы можем понять, что происходит.
Во-первых, стандарт не определяет, как должна быть реализована виртуальная inheitence. Что касается стандарта, то нет даже такой вещи, как vtable.
ABCDerived
имеетBBase
иCBase
, Каждый из которых состоит изint
. Существует также единственный экземплярABase
, который состоит изint
. Наконец, есть vtable ptr.Размер
int
зависит от платформы - это не обязательно 4 байта. Но если мы предположим, что это 4 байта, и размер vtable также 4 байта, мы имеем:Однако это не означает, чтоint [ABCDerived] = 4 bytes int [CBase] = 4 bytes int [BBase] = 4 bytes int [ABase] = 4 bytes vtable = 4 bytes ------------- 20 bytes
sizeof (ABCDerived)
равно 20. Выравнивание приходит, чтобы играть здесь, а также. Стандарт позволяет компиляторам увеличивать размер объекта таким образом, чтобы он делился на несколько целых слов.Рассмотрим:
class ABase{ int iMem; }; class BBase : public virtual ABase { int iMem; }; class CBase : public virtual ABase { int iMem; }; class ABCDerived : public BBase, public CBase { int iMem; }; int main() { ABCDerived d; BBase& b = d; ABase* ab = &b; CBase& c = d; ABase* ac = &b; cout << hex << (void*) ab << "\n" << hex << (void*) ac << "\n"; cout << sizeof (d) << "\n" << sizeof (int) << "\n"; }
Вывод
28
на моей 64-битной машине Linux.Однако, если я повернусь при упаковке (с использованием зависящего от платформы переключателя #pragma):
#pragma pack (1)
Выход теперь равен 20.
Итак, длинное и короткое из всего этого:Здесь происходит тонна зависящих от платформы вещей. Вы не можете сказать, что размер объекта тот или иной, по крайней мере, без использования более зависимых от платформы вещей и знания того, как ваш компилятор фактически реализует виртуальное наследование. Размер его-это то, что он есть.