размер класса в виртуальном наследовании


Размер классов, как следует при использовании виртуального наследования..

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 4

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.

Итак, длинное и короткое из всего этого:

Здесь происходит тонна зависящих от платформы вещей. Вы не можете сказать, что размер объекта тот или иной, по крайней мере, без использования более зависимых от платформы вещей и знания того, как ваш компилятор фактически реализует виртуальное наследование. Размер его-это то, что он есть.

Размер должен быть 20 , так как вы использовали виртуальное наследование ABCDerived wont inherit ABase IMem дважды. Как вы говорите, это дает 24, может быть виртуальное наследование не поддерживается вашим компилятором.