Розглянемо цей приклад:
#include <iostream>
int main()
{
struct A {};
struct B : A {};
struct C : A, B {};
std::cout << sizeof(A) << '\n'; // 1
std::cout << sizeof(B) << '\n'; // 1
std::cout << sizeof(C) << '\n'; // 2, because of a duplicate base
struct E : A {virtual ~E() {}};
struct F : A, B {virtual ~F() {}};
std::cout << sizeof(E) << '\n'; // 8, the base overlaps the vtable pointer
std::cout << sizeof(F) << '\n'; // 16, but why?
}
Тут ви бачите, що для struct Eпорожнього базового класу (який на 1 байт великий) використовується те саме сховище, що і покажчик vtable, як і очікувалося.
Але для тих struct F, хто має дублікат порожньої бази, цього не відбувається. Що це викликає?
Я отримую такий же результат на GCC, Clang та MSVC. Наведені вище результати для x64, так sizeof(void *) == 8.
Цікаво, що для struct G : A, B {void *ptr;};GCC та Clang роблять EBO (розмір - 8), але MSVC - ні (розмір - 16).
Cта F? Зрештою, 2 * sizeof(void*) == 16на x86_64, як ви вже говорили. Компілятор не може повністю оптимізувати (як сказав Story Teller), і так не робить.
A, успадкований через B, не може бути доступний. Це добре. Тільки якщо ви насправді намагаєтесь отримати доступ до нього, як у вашому прикладі, ви отримуєте помилку.
C(які успадковують відA,B) ви отримаєте інший результат , ніж спадкування формиAіBбезпосередньо