Почему в следующем коде размер Parent совпадает с размером Child (даже если Child добавляет переменную-член)? Еще одно странное поведение: если я закомментирую строку, в которой определен b, размер Child останется прежним, но если я добавлю еще одну переменную (int b, c;), то sizeof даст 24. Объяснение того, почему это происходит, было бы очень признательно (:
#include <iostream>
class Parent {
int a = 0;
public:
virtual void foo() {}
};
class Child : public Parent {
int b; // this line doesn't affect the output
};
int main() {
std::cout << sizeof(Parent) << ", " << sizeof(Child);
return 0;
}
// Output is : 16, 16
Примечание: я впервые задаю здесь вопросы, поэтому не стесняйтесь просить меня отредактировать их, если они неясны или плохо сформулированы.
🤔 А знаете ли вы, что...
C++ был разработан в начале 1980-х годов Бьярном Страуструпом в Bell Labs.
Это связано с наличием виртуальной функции foo
:
virtual void foo() {}
Компилятор генерирует указатель на таблицу адресов виртуальных функций, который, похоже, в вашей системе равен 8
, а sizeof( int )
равен 4
. Таким образом, из-за распределения адреса по 8
байтам родительского класса его размер равен 16
.
Если вы удалите виртуальную функцию в родительском классе или хотя бы объявите член данных a
родительского класса с типом sizeof
которого равен sizeof
указателя на таблицу адресов виртуальных функций, то размеры классов будут равны другой
Вот две демонстрационные программы.
#include <iostream>
class Parent
{
int a = 0;
public:
// virtual void foo() {}
};
class Child : public Parent
{
int b;
};
int main()
{
std::cout << sizeof( Parent ) << ", " << sizeof( Child ) << '\n';
}
Вывод программы
4, 8
И
#include <iostream>
class Parent
{
long long int a = 0;
public:
virtual void foo() {}
};
class Child : public Parent
{
int b;
};
int main()
{
std::cout << sizeof( Parent ) << ", " << sizeof( Child ) << '\n';
}
Вывод программы
16, 24
Спасибо всем за ваши ответы/комментарии, я думаю, что ответ @Peter хорошо это объясняет: это связано с выравниванием 8 байтов, требуемым виртуальной функцией (по крайней мере, в моей системе). Так интересно, без виртуальной функции:
class Parent
{
int a = 0;
public:
// virtual void foo() {}
};
Результатом alignof(Parent)
является 4
, поэтому любая отдельная переменная int
будет влиять на результат sizeof
, но с помощью виртуальной функции:
class Parent
{
int a = 0;
public:
virtual void foo() {}
};
alignof(Parent)
теперь дает 8
, поэтому для изменения результата int
потребуются еще две переменные sizeof
.