Размер класса с виртуальным наследованием - PullRequest
1 голос
/ 11 июля 2020

Я пробовал приведенную ниже программу по виртуальному наследованию с https://www.onlinegdb.com/online_c++_compiler ..

#include <iostream>

using namespace std;

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()
{
    cout << "Int is :" << sizeof(int) <<endl;
    cout << "Abase is :" << sizeof(ABase) << endl;
    cout << "Abase is :" << sizeof(BBase) << endl;
    cout << "Abase is :" << sizeof(CBase) << endl;
    cout << "Abase is :" << sizeof(ABCDerived) << endl;
    return 0;
}

Размеры ABase, BBase, CBase и ABCDerived: 4, 16, 16 и 40 соответственно.

Обычно из того, что я читаю, я ожидаю, что BBase и CBase будут равны 12 байтам (8 байтов для двух переменных типа int и 4 байта для vPtr). Но я получаю 16, даже если я предполагаю, что vPtr использует 8 байтов, почему ABCDerived имеет размер 40 байтов?

Инструмент OnlineGBD утверждает, что использует компилятор G ++ / C ++.

Я знаю аналогичные вопросы задавались на этом форуме ранее, но я не могу понять этот расчет размера.

1 Ответ

1 голос
/ 11 июля 2020

Если вы используете #pragma pack(1) для удаления отступов, чтобы было меньше путаницы, подумайте:

#include <iostream>

using namespace std;
#pragma pack(1)

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()
{
    cout << "void* is :" << sizeof(void*) << endl;
    cout << "Int is :" << sizeof(int) <<endl;
    cout << "Abase is :" << sizeof(ABase) << endl;
    cout << "Bbase is :" << sizeof(BBase) << endl;
    cout << "Cbase is :" << sizeof(CBase) << endl;
    cout << "ABCDerived is :" << sizeof(ABCDerived) << endl;
}

Это даст вам результат:

void* is :8
Int is :4
Abase is :4
Bbase is :16
Cbase is :16
ABCDerived is :32

Bbase и Cbase содержат:

  • и Abase виртуальную базу (4 байта)
  • указатель на свою Abase виртуальную базу (8 байтов)
  • свою собственную int член (4 байта)

всего = 16 байтов

ABCDerived содержит:

  • a Bbase base (16 байтов)
  • a Cbase base (который просто должен хранить int член + указатель на существующую Abase виртуальную базу, унаследованную через Bbase = 4 + 8 = 12 байт)
  • собственный int член (4 байта)

всего = 32 байта

...