Rozważ ten przykład:
#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?
}
Tutaj możesz to zobaczyć struct E pustej klasy podstawowej (która ma duży rozmiar 1 bajt), zgodnie z oczekiwaniami, używa tej samej pamięci co wskaźnik vtable.
Ale dla struct F , która ma zduplikowaną pustą bazę, tak się nie dzieje. Co to powoduje?
Ten sam wynik otrzymuję w GCC, Clang i MSVC. Powyższe wyniki dotyczą x64, więc sizeof(void *) == 8.
Co ciekawe, dla struct G : A, B {void *ptr;};GCC i Clanga wykonują EBO (rozmiar to 8), ale MSVC nie (rozmiar to 16).
Ci F? W końcu 2 * sizeof(void*) == 16na x86_64, jak powiedziałeś. Kompilator nie może w pełni zoptymalizować (jak powiedział Story Teller), a więc nie.
A, odziedziczonego przez B. W porządku. Tylko jeśli faktycznie spróbujesz uzyskać do niego dostęp, tak jak w twoim przykładzie, pojawi się błąd.
C(dziedziczącA,B) otrzymujesz inny wynik niż dziedziczenie formyAiBbezpośrednio